Skip to content

Commit

Permalink
feat: backend ssh public key validation
Browse files Browse the repository at this point in the history
* replaced regexp in SSH key validators with call to backend validation method
* this unifies the process and offers a more strict validation
  • Loading branch information
xflord committed Oct 31, 2023
1 parent 585f94f commit 558785c
Show file tree
Hide file tree
Showing 8 changed files with 289 additions and 88 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,19 @@ public static Request validatePreferredEmailChange(int userId, String token, Jso

}

/**
* Validate ssh public key, throws exception if validation fails
*
* @param sshKey ssh public key to verify
* @return Request unique request
*/
public static Request validateSSHKey(String sshKey, JsonEvents events) {
JsonClient client = new JsonClient(events);
client.put("sshKey", sshKey);

return client.call(USERS_MANAGER + "validateSSHKey");
}

/**
* Change password in selected namespace
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.VerticalPanel;
import cz.metacentrum.perun.wui.json.Events;
import cz.metacentrum.perun.wui.model.PerunException;
import cz.metacentrum.perun.wui.registrar.client.resources.PerunRegistrarResources;
import cz.metacentrum.perun.wui.registrar.widgets.items.validators.ListBoxValidator;
import cz.metacentrum.perun.wui.registrar.widgets.items.validators.SshKeysListBoxValidator;
Expand All @@ -19,7 +20,9 @@
import org.gwtbootstrap3.client.ui.html.Paragraph;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* Represents ListBox form item.
Expand All @@ -30,6 +33,7 @@ public class ListBox extends WidgetBox {

private final ListBoxValidator validator;
List<ExtendedTextBox> inputList;
Map<ExtendedTextBox, BlurHandler> handlers = new HashMap<>();

public ListBox(PerunForm form, ApplicationFormItemData item, String lang) {
super(form, item, lang);
Expand Down Expand Up @@ -95,13 +99,48 @@ protected void setValidationTriggers() {
if (isOnlyPreview()) {
return;
}
for (ExtendedTextBox input : inputList) {
input.addBlurHandler(new BlurHandler() {
if ("urn:perun:user:attribute-def:def:sshPublicKey".equals(this.getItemData().getFormItem().getPerunDestinationAttribute())) {
final Events<Boolean> nothingEvent = new Events<Boolean>() {
@Override
public void onBlur(BlurEvent event) {
validateLocal();
public void onFinished(Boolean result) {

}

@Override
public void onError(PerunException error) {

}
});

@Override
public void onLoadingStart() {

}
};

for (ExtendedTextBox input : inputList) {

if (!handlers.containsKey(input)) {
BlurHandler handler = new BlurHandler() {
@Override
public void onBlur(BlurEvent event) {
validate(nothingEvent);
}
};
input.addBlurHandler(handler);
handlers.put(input, handler);
}

}

} else {
for (ExtendedTextBox input : inputList) {
input.addBlurHandler(new BlurHandler() {
@Override
public void onBlur(BlurEvent event) {
validateLocal();
}
});
}
}
}

Expand Down Expand Up @@ -154,6 +193,7 @@ protected void generateItemWithRemoveButton(VerticalPanel vp) {
PerunButton removeButton = new PerunButton("", new ClickHandler() {
public void onClick(ClickEvent event) {
inputList.remove(input);
handlers.remove(input);
vp.remove(hp);
validateLocal();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.user.client.ui.Widget;
import cz.metacentrum.perun.wui.json.Events;
import cz.metacentrum.perun.wui.model.PerunException;
import cz.metacentrum.perun.wui.model.beans.ApplicationFormItemData;
import cz.metacentrum.perun.wui.registrar.widgets.PerunForm;
import cz.metacentrum.perun.wui.registrar.widgets.items.validators.PerunFormItemValidator;
Expand Down Expand Up @@ -87,12 +88,38 @@ public void setValidationTriggers() {
if (isOnlyPreview()) {
return;
}
getBox().addBlurHandler(new BlurHandler() {
@Override
public void onBlur(BlurEvent event) {
validateLocal();
}
});
if ("urn:perun:user:attribute-def:def:sshPublicKey".equals(this.getItemData().getFormItem().getPerunDestinationAttribute())) {
final Events<Boolean> nothingEvent = new Events<Boolean>() {
@Override
public void onFinished(Boolean result) {

}

@Override
public void onError(PerunException error) {

}

@Override
public void onLoadingStart() {

}
};

getBox().addBlurHandler(new BlurHandler() {
@Override
public void onBlur(BlurEvent event) {
validate(nothingEvent);
}
});
} else {
getBox().addBlurHandler(new BlurHandler() {
@Override
public void onBlur(BlurEvent event) {
validateLocal();
}
});
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.user.client.ui.Widget;
import cz.metacentrum.perun.wui.json.Events;
import cz.metacentrum.perun.wui.model.PerunException;
import cz.metacentrum.perun.wui.model.beans.ApplicationFormItemData;
import cz.metacentrum.perun.wui.registrar.widgets.PerunForm;
import cz.metacentrum.perun.wui.registrar.widgets.items.validators.PerunFormItemValidator;
Expand Down Expand Up @@ -104,12 +105,38 @@ public void setValidationTriggers() {
if (isOnlyPreview()) {
return;
}
getBox().addBlurHandler(new BlurHandler() {
@Override
public void onBlur(BlurEvent event) {
validateLocal();
}
});
if ("urn:perun:user:attribute-def:def:sshPublicKey".equals(this.getItemData().getFormItem().getPerunDestinationAttribute())) {
final Events<Boolean> nothingEvent = new Events<Boolean>() {
@Override
public void onFinished(Boolean result) {

}

@Override
public void onError(PerunException error) {

}

@Override
public void onLoadingStart() {

}
};

getBox().addBlurHandler(new BlurHandler() {
@Override
public void onBlur(BlurEvent event) {
validate(nothingEvent);
}
});
} else {
getBox().addBlurHandler(new BlurHandler() {
@Override
public void onBlur(BlurEvent event) {
validateLocal();
}
});
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ enum Result {
INVALID_FORMAT_EMAIL,
LOGIN_NOT_AVAILABLE,
CHECKING_LOGIN,
CHECKING_SSH,
CANT_CHECK_LOGIN,
EMPTY_PASSWORD,
PASSWORD_TOO_SHORT,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
package cz.metacentrum.perun.wui.registrar.widgets.items.validators;

import com.google.gwt.regexp.shared.MatchResult;
import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.core.client.JavaScriptObject;
import cz.metacentrum.perun.wui.json.Events;
import cz.metacentrum.perun.wui.json.JsonEvents;
import cz.metacentrum.perun.wui.json.managers.UsersManager;
import cz.metacentrum.perun.wui.model.PerunException;
import cz.metacentrum.perun.wui.registrar.widgets.items.ListBox;
import cz.metacentrum.perun.wui.widgets.boxes.ExtendedTextBox;
import org.gwtbootstrap3.client.ui.constants.ValidationState;

import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

/**
* Validator for ListBox
*
* @author Jakub Hejda <[email protected]>
*/
public class SshKeysListBoxValidator extends ListBoxValidator {

RegExp regExp = RegExp.compile("^(" +
"(ssh-(rsa|dss|ed25519)([email protected])?)|" +
"(sk-(ssh-ed25519|ecdsa-sha2-nistp256)(-cert-v01)[email protected])|" +
"(ecdsa-sha2-nistp(256|384|521)([email protected])?))" +
" (([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?)( [^,\n]+)?$");
static String wrongValues = "";
Map<Integer, String> wrongVals = new TreeMap<>();

@Override
public boolean validateLocal(ListBox listBox) {
Expand All @@ -26,34 +30,64 @@ public boolean validateLocal(ListBox listBox) {
listBox.setRawStatus(getTransl().cantBeEmpty(), ValidationState.ERROR);
return false;
}
listBox.setStatus(ValidationState.SUCCESS);
return true;
}

if (listBox.getValue() != null && !listBox.getValue().isEmpty()) {
@Override
public void validate(ListBox listBox, Events<Boolean> events) {
events.onLoadingStart();

String wrongValues = "";
int index = 1;
for (ExtendedTextBox extendedTextBox : listBox.getListValue()) {
String sshKey = extendedTextBox.getValue();
if (!validateLocal(listBox)) {
events.onFinished(false);
return;
}

if (sshKey.contains(",")) {
setResult(Result.INVALID_FORMAT);
listBox.setStatus(getTransl().sshKeySeparatorNotAllowed(), ValidationState.ERROR);
return false;
}
if (listBox.getValue() == null || listBox.getValue().isEmpty()) {
events.onFinished(true);
return;
}

MatchResult matcher = regExp.exec(sshKey);
if (matcher == null) {
wrongValues += "<br>" + index + ". " + (sshKey.length() > 25 ? sshKey.substring(0, 23) + "..." : sshKey);
}
index++;
}
if (!wrongValues.isEmpty()) {

wrongValues = "";
wrongVals.clear();
int index = 1;
for (ExtendedTextBox extendedTextBox : listBox.getListValue()) {
String sshKey = extendedTextBox.getValue();

if (sshKey.contains(",")) {
setResult(Result.INVALID_FORMAT);
listBox.setRawStatus(getTransl().incorrectFormatItemList() + " <b>" + wrongValues + "</b>", ValidationState.ERROR);
return false;
listBox.setStatus(getTransl().sshKeySeparatorNotAllowed(), ValidationState.ERROR);
events.onFinished(false);
}
}

listBox.setStatus(ValidationState.SUCCESS);
return true;
int currIndex = index;
UsersManager.validateSSHKey(sshKey, new JsonEvents() {
@Override
public void onFinished(JavaScriptObject result) {
if (wrongValues.isEmpty()) {
events.onFinished(true);
listBox.setStatus(ValidationState.SUCCESS);
}
}

@Override
public void onError(PerunException error) {
wrongVals.put(currIndex, sshKey);
wrongValues += "<br>" + currIndex + ". " + (sshKey.length() > 25 ? sshKey.substring(0, 23) + "..." : sshKey);
setResult(Result.INVALID_FORMAT);
listBox.setRawStatus(getTransl().incorrectFormatItemList() + " <b> " + wrongVals.entrySet().stream().map((entry) -> entry.getKey() + ". " +
(entry.getValue().length() > 25 ? entry.getValue().substring(0,23) + "..." : entry.getValue())) + "</b>", ValidationState.ERROR);
events.onFinished(false);
}

@Override
public void onLoadingStart() {
setResult(Result.CHECKING_SSH);
listBox.unsetStatus();
}
});
index++;
}
}
}
Loading

0 comments on commit 558785c

Please sign in to comment.