mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-21 21:25:38 +00:00
bug4811: started to make SSHKeyPair a secured type and adding security-aware UI support for SSH key management
This commit is contained in:
@@ -6,3 +6,6 @@ Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Vendor: SAP
|
||||
Automatic-Module-Name: com.sap.sailing.landscape.common
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Require-Bundle: com.sap.sse.security.common,
|
||||
com.sap.sse.common
|
||||
Export-Package: com.sap.sailing.landscape.common
|
||||
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package com.sap.sailing.landscape.common;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sap.sse.security.shared.HasPermissions;
|
||||
import com.sap.sse.security.shared.impl.HasPermissionsImpl;
|
||||
import com.sap.sse.security.shared.impl.SecuredSecurityTypes;
|
||||
|
||||
/**
|
||||
* The basic types of logical objects provided by the landscape bundle that themselves have permissions governing how
|
||||
* users may deal with them.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public class SecuredLandscapeTypes extends HasPermissionsImpl {
|
||||
private static final long serialVersionUID = -5052828472297142038L;
|
||||
private static Set<HasPermissions> allInstances = new HashSet<>();
|
||||
|
||||
public SecuredLandscapeTypes(String logicalTypeName, Action... availableActions) {
|
||||
super(logicalTypeName, availableActions);
|
||||
allInstances.add(this);
|
||||
}
|
||||
|
||||
public SecuredLandscapeTypes(String logicalTypeName) {
|
||||
super(logicalTypeName);
|
||||
allInstances.add(this);
|
||||
}
|
||||
|
||||
public static Iterable<HasPermissions> getAllInstances() {
|
||||
return Collections.unmodifiableSet(allInstances);
|
||||
}
|
||||
|
||||
/**
|
||||
* The type-relative identifier consists of the region ID and the key name.
|
||||
*/
|
||||
public static final HasPermissions SSH_KEY = new SecuredLandscapeTypes("SSH_KEY");
|
||||
|
||||
public static enum LandscapeActions implements Action {
|
||||
MANAGE;
|
||||
|
||||
private static final Action[] ALL_ACTIONS = new Action[] { MANAGE,
|
||||
DefaultActions.CHANGE_OWNERSHIP, DefaultActions.CHANGE_ACL };
|
||||
}
|
||||
|
||||
public static final HasPermissions LANDSCAPE = new SecuredSecurityTypes("LANDSCAPE", LandscapeActions.ALL_ACTIONS);
|
||||
}
|
||||
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
package com.sap.sailing.landscape.ui.client;
|
||||
|
||||
public interface AwsAccessKeyProvider {
|
||||
String getAwsAccessKeyId();
|
||||
String getAwsSecret();
|
||||
}
|
||||
+13
-2
@@ -60,7 +60,7 @@ import com.sap.sse.security.ui.client.UserService;
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
*/
|
||||
public class LandscapeManagementPanel extends VerticalPanel {
|
||||
public class LandscapeManagementPanel extends VerticalPanel implements AwsAccessKeyProvider {
|
||||
private final LandscapeManagementWriteServiceAsync landscapeManagementService;
|
||||
private final TableWrapperWithSingleSelectionAndFilter<String, StringMessages, AdminConsoleTableResources> regionsTable;
|
||||
private final TableWrapperWithSingleSelectionAndFilter<MongoEndpointDTO, StringMessages, AdminConsoleTableResources> mongoEndpointsTable;
|
||||
@@ -104,7 +104,8 @@ public class LandscapeManagementPanel extends VerticalPanel {
|
||||
awsCredentialsGrid.setWidget(1, 0, new Label(stringMessages.awsSecret()));
|
||||
awsSecretPasswordTextBox = new PasswordTextBox();
|
||||
awsCredentialsGrid.setWidget(1, 1, awsSecretPasswordTextBox);
|
||||
final SshKeyManagementPanel sshKeyManagementPanel = new SshKeyManagementPanel(stringMessages, userService, landscapeManagementService, tableResources, errorReporter);
|
||||
final SshKeyManagementPanel sshKeyManagementPanel = new SshKeyManagementPanel(stringMessages, userService,
|
||||
landscapeManagementService, tableResources, errorReporter, /* access key provider */ this);
|
||||
final CaptionPanel sshKeysCaptionPanel = new CaptionPanel(stringMessages.sshKeys());
|
||||
awsCredentialsAndSshKeys.add(sshKeysCaptionPanel);
|
||||
sshKeysCaptionPanel.add(sshKeyManagementPanel);
|
||||
@@ -214,4 +215,14 @@ public class LandscapeManagementPanel extends VerticalPanel {
|
||||
RemoteServiceMappingConstants.landscapeManagementServiceRemotePath, HEADER_FORWARD_TO_MASTER);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAwsAccessKeyId() {
|
||||
return awsAccessKeyTextBox.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAwsSecret() {
|
||||
return awsSecretPasswordTextBox.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -14,4 +14,6 @@ public interface LandscapeManagementWriteService extends RemoteService {
|
||||
MongoEndpointDTO getMongoEndpoint(String awsAccessKey, String awsSecret, String region, String replicaSetName);
|
||||
|
||||
ArrayList<SSHKeyPairDTO> getSshKeys(String awsAccessKey, String awsSecret, String regionId);
|
||||
|
||||
void removeSshKey(String awsAccessKey, String awsSecret, SSHKeyPairDTO keyPair);
|
||||
}
|
||||
|
||||
+2
@@ -17,4 +17,6 @@ public interface LandscapeManagementWriteServiceAsync {
|
||||
|
||||
void getSshKeys(String awsAccessKey, String awsSecret, String regionId,
|
||||
AsyncCallback<ArrayList<SSHKeyPairDTO>> callback);
|
||||
|
||||
void removeSshKey(String awsAccessKey, String awsSecret, SSHKeyPairDTO keyPair, AsyncCallback<Void> asyncCallback);
|
||||
}
|
||||
|
||||
+21
-2
@@ -6,6 +6,7 @@ import java.util.Optional;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
import com.sap.sailing.landscape.common.SecuredLandscapeTypes;
|
||||
import com.sap.sailing.landscape.ui.client.i18n.StringMessages;
|
||||
import com.sap.sailing.landscape.ui.shared.SSHKeyPairDTO;
|
||||
import com.sap.sse.common.Util;
|
||||
@@ -16,18 +17,24 @@ import com.sap.sse.gwt.client.celltable.TableWrapperWithSingleSelectionAndFilter
|
||||
import com.sap.sse.gwt.client.controls.busyindicator.BusyIndicator;
|
||||
import com.sap.sse.gwt.client.controls.busyindicator.SimpleBusyIndicator;
|
||||
import com.sap.sse.security.ui.client.UserService;
|
||||
import com.sap.sse.security.ui.client.component.AccessControlledButtonPanel;
|
||||
|
||||
public class SshKeyManagementPanel extends VerticalPanel {
|
||||
private final LandscapeManagementWriteServiceAsync landscapeManagementService;
|
||||
private final TableWrapperWithSingleSelectionAndFilter<SSHKeyPairDTO, StringMessages, AdminConsoleTableResources> sshKeyTable;
|
||||
private final BusyIndicator sshKeyLoadingBusy;
|
||||
private final ErrorReporter errorReporter;
|
||||
|
||||
|
||||
public SshKeyManagementPanel(StringMessages stringMessages, UserService userService,
|
||||
LandscapeManagementWriteServiceAsync landscapeManagementService, AdminConsoleTableResources tableResources,
|
||||
ErrorReporter errorReporter) {
|
||||
ErrorReporter errorReporter, AwsAccessKeyProvider awsAccessKeyProvider) {
|
||||
this.landscapeManagementService = landscapeManagementService;
|
||||
this.errorReporter = errorReporter;
|
||||
final AccessControlledButtonPanel buttonPanel = new AccessControlledButtonPanel(userService, SecuredLandscapeTypes.SSH_KEY);
|
||||
add(buttonPanel);
|
||||
buttonPanel.addCreateAction(stringMessages.add(), ()->{
|
||||
// TODO here goes the add SSH key logic: pop up a dialog for file upload, local generation, generation in AWS, and text areas for pasting keys as text
|
||||
});
|
||||
sshKeyTable =
|
||||
new TableWrapperWithSingleSelectionAndFilter<SSHKeyPairDTO, StringMessages, AdminConsoleTableResources>(stringMessages, errorReporter, /* enablePager */ true,
|
||||
Optional.of(new EntityIdentityComparator<SSHKeyPairDTO>() {
|
||||
@@ -55,6 +62,18 @@ public class SshKeyManagementPanel extends VerticalPanel {
|
||||
add(sshKeyTable);
|
||||
sshKeyLoadingBusy = new SimpleBusyIndicator();
|
||||
add(sshKeyLoadingBusy);
|
||||
buttonPanel.addRemoveAction(stringMessages.remove(), sshKeyTable.getSelectionModel(), /* withConfirmation */ true, ()->{
|
||||
landscapeManagementService.removeSshKey(awsAccessKeyProvider.getAwsAccessKeyId(), awsAccessKeyProvider.getAwsSecret(),
|
||||
sshKeyTable.getSelectionModel().getSelectedObject(), new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError(caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void result) {}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public void showKeysInRegion(String awsAccessKey, String awsSecret, String regionId) {
|
||||
|
||||
+10
-3
@@ -5,6 +5,7 @@ import java.util.Collections;
|
||||
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
|
||||
import com.sap.sailing.landscape.common.SecuredLandscapeTypes;
|
||||
import com.sap.sailing.landscape.ui.client.LandscapeManagementWriteService;
|
||||
import com.sap.sailing.landscape.ui.shared.MongoEndpointDTO;
|
||||
import com.sap.sailing.landscape.ui.shared.SSHKeyPairDTO;
|
||||
@@ -19,7 +20,7 @@ import com.sap.sse.landscape.mongodb.MongoProcess;
|
||||
import com.sap.sse.landscape.mongodb.MongoProcessInReplicaSet;
|
||||
import com.sap.sse.landscape.mongodb.MongoReplicaSet;
|
||||
import com.sap.sse.landscape.ssh.SSHKeyPair;
|
||||
import com.sap.sse.security.shared.impl.SecuredSecurityTypes;
|
||||
import com.sap.sse.security.shared.HasPermissions.DefaultActions;
|
||||
|
||||
import software.amazon.awssdk.services.ec2.model.KeyPairInfo;
|
||||
|
||||
@@ -32,7 +33,7 @@ public class LandscapeManagementWriteServiceImpl extends ResultCachingProxiedRem
|
||||
|
||||
@Override
|
||||
public ArrayList<String> getRegions() {
|
||||
SecurityUtils.getSubject().checkPermission(SecuredSecurityTypes.LANDSCAPE.getStringPermission(SecuredSecurityTypes.LandscapeActions.MANAGE));
|
||||
SecurityUtils.getSubject().checkPermission(SecuredLandscapeTypes.LANDSCAPE.getStringPermission(SecuredLandscapeTypes.LandscapeActions.MANAGE));
|
||||
final ArrayList<String> result = new ArrayList<>();
|
||||
Util.addAll(Util.map(AwsLandscape.obtain().getRegions(), r->r.getId()), result);
|
||||
return result;
|
||||
@@ -40,7 +41,7 @@ public class LandscapeManagementWriteServiceImpl extends ResultCachingProxiedRem
|
||||
|
||||
@Override
|
||||
public ArrayList<MongoEndpointDTO> getMongoEndpoints(String awsAccessKey, String awsSecret, String region) {
|
||||
SecurityUtils.getSubject().checkPermission(SecuredSecurityTypes.LANDSCAPE.getStringPermission(SecuredSecurityTypes.LandscapeActions.MANAGE));
|
||||
SecurityUtils.getSubject().checkPermission(SecuredLandscapeTypes.LANDSCAPE.getStringPermission(SecuredLandscapeTypes.LandscapeActions.MANAGE));
|
||||
final ArrayList<MongoEndpointDTO> result = new ArrayList<>();
|
||||
for (final MongoEndpoint mongoEndpoint : AwsLandscape.obtain(awsAccessKey, awsSecret).getMongoEndpoints(new AwsRegion(region))) {
|
||||
final MongoEndpointDTO dto;
|
||||
@@ -78,4 +79,10 @@ public class LandscapeManagementWriteServiceImpl extends ResultCachingProxiedRem
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSshKey(String awsAccessKey, String awsSecret, SSHKeyPairDTO keyPair) {
|
||||
SecurityUtils.getSubject().checkPermission(SecuredLandscapeTypes.SSH_KEY.getStringPermission(DefaultActions.DELETE));
|
||||
AwsLandscape.obtain(awsAccessKey, awsSecret).deleteKeyPair(new AwsRegion(keyPair.getRegionId()), keyPair.getName());
|
||||
}
|
||||
}
|
||||
|
||||
+25
-17
@@ -1,23 +1,21 @@
|
||||
package com.sap.sailing.landscape.ui.shared;
|
||||
|
||||
import com.google.gwt.user.client.rpc.IsSerializable;
|
||||
import com.sap.sailing.landscape.common.SecuredLandscapeTypes;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.security.shared.HasPermissions;
|
||||
import com.sap.sse.security.shared.QualifiedObjectIdentifier;
|
||||
import com.sap.sse.security.shared.TypeRelativeObjectIdentifier;
|
||||
import com.sap.sse.security.shared.dto.NamedSecuredObjectDTO;
|
||||
|
||||
public class SSHKeyPairDTO implements IsSerializable {
|
||||
private String regionId;
|
||||
private String name;
|
||||
private String creatorName;
|
||||
private TimePoint creationTime;
|
||||
|
||||
@Deprecated
|
||||
SSHKeyPairDTO() {
|
||||
// for GWT RPC serialization only
|
||||
}
|
||||
public class SSHKeyPairDTO extends NamedSecuredObjectDTO {
|
||||
private static final long serialVersionUID = -9174909996567452216L;
|
||||
private final String regionId;
|
||||
private final String creatorName;
|
||||
private final TimePoint creationTime;
|
||||
|
||||
public SSHKeyPairDTO(String regionId, String name, String creatorName, TimePoint creationTime) {
|
||||
super();
|
||||
super(name);
|
||||
this.regionId = regionId;
|
||||
this.name = name;
|
||||
this.creatorName = creatorName;
|
||||
this.creationTime = creationTime;
|
||||
}
|
||||
@@ -26,10 +24,6 @@ public class SSHKeyPairDTO implements IsSerializable {
|
||||
return regionId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getCreatorName() {
|
||||
return creatorName;
|
||||
}
|
||||
@@ -37,4 +31,18 @@ public class SSHKeyPairDTO implements IsSerializable {
|
||||
public TimePoint getCreationTime() {
|
||||
return creationTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QualifiedObjectIdentifier getIdentifier() {
|
||||
return getPermissionType().getQualifiedObjectIdentifier(getTypeRelativeObjectIdentifier());
|
||||
}
|
||||
|
||||
public TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier() {
|
||||
return new TypeRelativeObjectIdentifier(getRegionId(), getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public HasPermissions getPermissionType() {
|
||||
return SecuredLandscapeTypes.SSH_KEY;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.sap.sse.security.shared.dto;
|
||||
import com.sap.sse.security.shared.WithQualifiedObjectIdentifier;
|
||||
|
||||
public interface SecuredDTO extends WithQualifiedObjectIdentifier {
|
||||
|
||||
AccessControlListDTO getAccessControlList();
|
||||
|
||||
OwnershipDTO getOwnership();
|
||||
|
||||
-9
@@ -108,13 +108,4 @@ public class SecuredSecurityTypes extends HasPermissionsImpl {
|
||||
* type-relative identifier is the server name
|
||||
*/
|
||||
public static final HasPermissions SERVER = new SecuredSecurityTypes("SERVER", ServerActions.ALL_ACTIONS);
|
||||
|
||||
public static enum LandscapeActions implements Action {
|
||||
MANAGE;
|
||||
|
||||
private static final Action[] ALL_ACTIONS = new Action[] { MANAGE,
|
||||
DefaultActions.CHANGE_OWNERSHIP, DefaultActions.CHANGE_ACL };
|
||||
}
|
||||
|
||||
public static final HasPermissions LANDSCAPE = new SecuredSecurityTypes("LANDSCAPE", LandscapeActions.ALL_ACTIONS);
|
||||
}
|
||||
|
||||
+2
-2
@@ -141,8 +141,8 @@ public class AccessControlledButtonPanel extends Composite {
|
||||
if (selectionModel == null) {
|
||||
throw new IllegalArgumentException("Selection model for a remove action must not be null");
|
||||
}
|
||||
ClickHandler handler = wrap(removePermissionCheck, callback);
|
||||
Button button = withConfirmation
|
||||
final ClickHandler handler = wrap(removePermissionCheck, callback);
|
||||
final Button button = withConfirmation
|
||||
? new SelectedElementsCountingButton<T>(text, selectionModel, StringMessages.INSTANCE::doYouReallyWantToRemoveSelectedElements,
|
||||
handler)
|
||||
: new SelectedElementsCountingButton<T>(text, selectionModel, handler);
|
||||
|
||||
-1
@@ -19,7 +19,6 @@ import com.sap.sse.common.Named;
|
||||
* @author Dmitry Bilyk
|
||||
*
|
||||
*/
|
||||
|
||||
public class SelectedElementsCountingButton<T extends Named> extends Button {
|
||||
/**
|
||||
* Constructs the button without a confirmation callback installed. The {@code clickHandler}
|
||||
|
||||
Reference in New Issue
Block a user