Enable/disable kie logging #271

Allow to define a JMT token to give access to a project over reverse proxy #274
Hot deploy management #269 => UI for defiinition
This commit is contained in:
nheron 2021-07-24 22:11:11 +02:00
commit 488870e587
32 changed files with 664 additions and 167 deletions

View file

@ -0,0 +1,64 @@
package org.chtijbug.drools.console.middle;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.chtijbug.drools.proxy.persistence.model.ProjectPersist;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.Date;
@Service
public class JwtService {
@Value("${secretkey}")
public String secretKey;
public String createJWT(ProjectPersist projectPersist, long ttlMillis) {
//The JWT signature algorithm we will be using to sign the token
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
//We will sign our JWT with our ApiKey secret
byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(secretKey);
Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
//Let's set the JWT Claims
JwtBuilder builder = Jwts.builder().setId(projectPersist.getUuid())
.setIssuedAt(now)
.setSubject("api")
.setIssuer("pymma")
.claim("groupID",projectPersist.getGroupID())
.claim("artifactID",projectPersist.getArtifactID())
.claim("branch",projectPersist.getBranch())
.claim("mainClass",projectPersist.getMainClass())
.claim("uuid",projectPersist.getUuid())
.signWith(signatureAlgorithm, signingKey);
//if it has been specified, let's add the expiration
if (ttlMillis >= 0) {
long expMillis = nowMillis + ttlMillis;
Date exp = new Date(expMillis);
builder.setExpiration(exp);
}
//Builds the JWT and serializes it to a compact, URL-safe string
return builder.compact();
}
public Claims decodeJWT(String jwt) {
return Jwts.parser()
.setSigningKey(DatatypeConverter.parseBase64Binary(secretKey))
.parseClaimsJws(jwt.replace("bearer","")).getBody();
}
}

View file

@ -187,7 +187,12 @@ public class ProjectPersistService {
projectPersist.setContainerID(projectPersist.getDeploymentName() + "-" + projectPersist.getProjectName());
projectPersist.getServerNames().clear();
ReverseProxyUpdate reverseProxyUpdate = new ReverseProxyUpdate();
reverseProxyUpdate.setPath("/" + projectPersist.getContainerID());
reverseProxyUpdate.setContainerID(projectPersist.getContainerID());
if (projectPersist.isUseJWTToConnect()) {
reverseProxyUpdate.setTokenUUID(projectPersist.getUuid());
}else{
reverseProxyUpdate.setPath("/" + projectPersist.getContainerID());
}
for (RuntimePersist runtimePersist : runtimePersists) {
List<String> names = new ArrayList<>();
names.add(runtimePersist.getServerName());
@ -201,7 +206,8 @@ public class ProjectPersistService {
newContainer.setServerName(runtimePersist.getServerName());
newContainer.setGroupId(projectPersist.getGroupID());
newContainer.setArtifactId(projectPersist.getArtifactID());
newContainer.setProjectUUID(projectPersist.getUuid());
newContainer.setDisableRuleLogging(projectPersist.isDisableRuleLogging());
newContainer.setVersion(projectPersist.getProjectVersion());
containerRepository.save(newContainer);
List<ContainerRuntimePojoPersist> elts = containerRuntimeRepository.findByServerNameAndContainerId(runtimePersist.getServerName(), projectPersist.getContainerID());
@ -217,9 +223,15 @@ public class ProjectPersistService {
runtimePojoPersist.setHostname(runtimePersist.getHostname());
runtimePojoPersist.setContainerId(projectPersist.getContainerID());
runtimePojoPersist.setStatus(ContainerRuntimePojoPersist.STATUS.TODEPLOY.name());
runtimePojoPersist.setProjectUUID(projectPersist.getUuid());
runtimePojoPersist.setDisableRuleLogging(projectPersist.isDisableRuleLogging());
containerRuntimeRepository.save(runtimePojoPersist);
}
}else{
existingContainer.setDisableRuleLogging(projectPersist.isDisableRuleLogging());
existingContainer.setProjectUUID(projectPersist.getUuid());
containerRepository.save(existingContainer);
}
String hostName = runtimePersist.getServerUrl() + "/api/" + projectPersist.getContainerID();
@ -288,6 +300,7 @@ public class ProjectPersistService {
runtimePojoPersist.setHostname(server.getHostname());
runtimePojoPersist.setContainerId(projectPersist.getContainerID());
runtimePojoPersist.setStatus(ContainerRuntimePojoPersist.STATUS.TODEPLOY.name());
runtimePojoPersist.setProjectUUID(projectPersist.getUuid());
containerRuntimeRepository.save(runtimePojoPersist);
}
}

View file

@ -1,6 +1,11 @@
package org.chtijbug.drools.console.service;
import org.chtijbug.drools.console.service.model.ReturnPerso;
import org.chtijbug.drools.proxy.persistence.model.ContainerPojoPersist;
import org.chtijbug.drools.proxy.persistence.model.ContainerRuntimePojoPersist;
import org.chtijbug.drools.proxy.persistence.model.ProjectPersist;
import org.chtijbug.drools.proxy.persistence.repository.ContainerRepository;
import org.chtijbug.drools.proxy.persistence.repository.ContainerRuntimeRepository;
import org.chtijbug.drools.proxy.persistence.repository.RuntimeRepository;
import org.chtijbug.drools.proxy.persistence.model.RuntimePersist;
import org.kie.server.api.model.KieServerInfo;
@ -16,6 +21,8 @@ import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.List;
@Service
@DependsOn("applicationContext")
public class RuntimeService {
@ -26,6 +33,12 @@ public class RuntimeService {
@Autowired
private RuntimeRepository runtimeRepository;
@Autowired
private ContainerRepository containerRepository;
@Autowired
private ContainerRuntimeRepository containerRuntimeRepository;
private RestTemplate restTemplateKiewb = new RestTemplate();
public ReturnPerso<KieServerInfo> verifyIfKieServerExist(String url) {
@ -64,4 +77,22 @@ public class RuntimeService {
public void setRuntimeRepository(RuntimeRepository runtimeRepository) {
this.runtimeRepository = runtimeRepository;
}
public void updateRuntimes(ProjectPersist projectPersist) {
if (projectPersist!= null && projectPersist.getUuid()!= null) {
List<ContainerPojoPersist> containerPojoPersists = containerRepository.findByProjectUUID(projectPersist.getUuid());
for (ContainerPojoPersist containerPojoPersist : containerPojoPersists){
containerPojoPersist.setDisableRuleLogging(projectPersist.isDisableRuleLogging());
containerRepository.save(containerPojoPersist);
List<ContainerRuntimePojoPersist> containerRuntimePojoPersists = containerRuntimeRepository.findByContainerId(containerPojoPersist.getContainerId());
for (ContainerRuntimePojoPersist containerRuntimePojoPersist : containerRuntimePojoPersists){
containerRuntimePojoPersist.setDisableRuleLogging(projectPersist.isDisableRuleLogging());
containerRuntimePojoPersist.setProjectUUID(projectPersist.getUuid());
containerRuntimeRepository.save(containerRuntimePojoPersist);
}
}
}
}
}

View file

@ -1,18 +1,27 @@
package org.chtijbug.drools.console.vaadincomponent.componentview;
import com.vaadin.flow.component.AbstractField;
import com.vaadin.flow.component.ClickEvent;
import com.vaadin.flow.component.ComponentEventListener;
import com.vaadin.flow.component.HasValue;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.checkbox.Checkbox;
import com.vaadin.flow.component.dialog.Dialog;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.data.value.ValueChangeMode;
import io.jsonwebtoken.Claims;
import org.chtijbug.drools.console.middle.JwtService;
import org.chtijbug.drools.console.service.ProjectPersistService;
import org.chtijbug.drools.console.service.RuntimeService;
import org.chtijbug.drools.console.service.util.AppContext;
import org.chtijbug.drools.console.vaadincomponent.componentperso.ComboBoxPerso;
import org.chtijbug.drools.console.vaadincomponent.componentperso.TextFieldPerso;
import org.chtijbug.drools.console.view.DeploymentView;
import org.chtijbug.drools.proxy.persistence.model.ProjectPersist;
import org.vaadin.olli.ClipboardHelper;
public class DefineProject extends VerticalLayout {
@ -30,12 +39,31 @@ public class DefineProject extends VerticalLayout {
private Button valider;
private Checkbox disableRuleLoggingCheckbox;
private Checkbox enableHotDeployCheckbox;
private Checkbox useJWTToConnectCheckbox;
private TextFieldPerso jwtTokenTextField;
private TextFieldPerso jwtPeriod;
private Button createJWTButton;
private Button copyJWTTextButton;
private transient ProjectPersistService projectPersistService;
private transient RuntimeService runtimeService;
private boolean createMode;
private JwtService jwtService;
public DefineProject(DeploymentView deploymentView,Dialog dialog, ProjectPersist projectPersist){
jwtService = AppContext.getApplicationContext().getBean(JwtService.class);
runtimeService = AppContext.getApplicationContext().getBean(RuntimeService.class);
projectPersistService=AppContext.getApplicationContext().getBean(ProjectPersistService.class);
setClassName("creation-runtime-content");
@ -44,7 +72,7 @@ public class DefineProject extends VerticalLayout {
label.setClassName("creation-runtime-title");
add(label);
label2=new Label("this step is essential before you can associate your project with a workbench");
label2=new Label("this step is essential before you can work on your project");
label2.setClassName("creation-runtime-title2");
add(label2);
@ -98,6 +126,106 @@ public class DefineProject extends VerticalLayout {
add(processID);
enableHotDeployCheckbox = new Checkbox("Enable Hot deployment (needs 2 runtimes)");
if (projectPersist.isEnableHotDeploy()){
enableHotDeployCheckbox.setValue(true);
}else{
enableHotDeployCheckbox.setValue(false);
}
enableHotDeployCheckbox.addValueChangeListener(new HasValue.ValueChangeListener<AbstractField.ComponentValueChangeEvent<Checkbox, Boolean>>() {
@Override
public void valueChanged(AbstractField.ComponentValueChangeEvent<Checkbox, Boolean> checkboxBooleanComponentValueChangeEvent) {
projectPersist.setEnableHotDeploy(checkboxBooleanComponentValueChangeEvent.getValue());
}
});
add(enableHotDeployCheckbox);
disableRuleLoggingCheckbox = new Checkbox("Disable Rule logging");
if (projectPersist.isDisableRuleLogging()){
disableRuleLoggingCheckbox.setValue(true);
}else{
disableRuleLoggingCheckbox.setValue(false);
}
disableRuleLoggingCheckbox.addValueChangeListener(new HasValue.ValueChangeListener<AbstractField.ComponentValueChangeEvent<Checkbox, Boolean>>() {
@Override
public void valueChanged(AbstractField.ComponentValueChangeEvent<Checkbox, Boolean> checkboxBooleanComponentValueChangeEvent) {
projectPersist.setDisableRuleLogging(disableRuleLoggingCheckbox.getValue());
}
});
add(disableRuleLoggingCheckbox);
useJWTToConnectCheckbox =new Checkbox("Use JWT token to connect to API");
add(useJWTToConnectCheckbox);
jwtTokenTextField=new TextFieldPerso("JWT Token for API","",VaadinIcon.TASKS.create());
if (projectPersist.getJwtAPIToken()!= null
&& projectPersist.getJwtAPIToken().length()>0){
jwtTokenTextField.getTextField().setValue(projectPersist.getJwtAPIToken());
}
jwtTokenTextField.getTextField().setEnabled(false);
add(jwtTokenTextField);
copyJWTTextButton = new Button("Copy JWT token");
ClipboardHelper clipboardHelper = new ClipboardHelper(projectPersist.getJwtAPIToken(), copyJWTTextButton);
add(clipboardHelper);
jwtPeriod=new TextFieldPerso("JWT validity for API","",VaadinIcon.TASKS.create());
jwtPeriod.setEnabled(false);
if (projectPersist.getJwtAPIToken()!= null
&& projectPersist.getJwtAPIToken().length()>0){
try {
Claims claims = jwtService.decodeJWT(projectPersist.getJwtAPIToken());
jwtPeriod.getTextField().setValue(claims.getExpiration().toString());
}catch (Exception e){
}
jwtTokenTextField.getTextField().setValue(projectPersist.getJwtAPIToken());
}
add(jwtPeriod);
createJWTButton = new Button("Generate JWT token for one year");
createJWTButton.addClickListener(new ComponentEventListener<ClickEvent<Button>>() {
@Override
public void onComponentEvent(ClickEvent<Button> buttonClickEvent) {
String token = jwtService.createJWT(projectPersist, 1000*3600*24*(long)365);
projectPersist.setJwtAPIToken(token);
jwtTokenTextField.getTextField().setValue(token);
Claims claims = jwtService.decodeJWT(projectPersist.getJwtAPIToken());
jwtPeriod.getTextField().setValue(claims.getExpiration().toString());
}
});
add(createJWTButton);
if (projectPersist.isUseJWTToConnect()){
useJWTToConnectCheckbox.setValue(true);
}else{
useJWTToConnectCheckbox.setValue(false);
jwtTokenTextField.getTextField().setValue("");
jwtTokenTextField.setEnabled(false);
projectPersist.setJwtAPIToken(null);
createJWTButton.setEnabled(false);
jwtPeriod.getTextField().setValue("");
copyJWTTextButton.setEnabled(false);
}
useJWTToConnectCheckbox.addValueChangeListener(new HasValue.ValueChangeListener<AbstractField.ComponentValueChangeEvent<Checkbox, Boolean>>() {
@Override
public void valueChanged(AbstractField.ComponentValueChangeEvent<Checkbox, Boolean> checkboxBooleanComponentValueChangeEvent) {
projectPersist.setUseJWTToConnect(useJWTToConnectCheckbox.getValue());
if (!useJWTToConnectCheckbox.getValue()){
jwtTokenTextField.getTextField().setValue("");
createJWTButton.setEnabled(false);
projectPersist.setJwtAPIToken(null);
jwtPeriod.getTextField().setValue("");
copyJWTTextButton.setEnabled(false);
}else{
jwtTokenTextField.setEnabled(true);
copyJWTTextButton.setEnabled(true);
createJWTButton.setEnabled(true);
}
}
});
valider=new Button("Save");
if (projectPersist.getProcessID()!= null
&& projectPersist.getProcessID().length()>0){
@ -112,6 +240,7 @@ public class DefineProject extends VerticalLayout {
if (createMode) {
projectPersist.setStatus(ProjectPersist.DEFINI);
}
runtimeService.updateRuntimes(projectPersist);
projectPersistService.getProjectRepository().save(projectPersist);
deploymentView.setDataProvider();
dialog.close();
@ -128,5 +257,10 @@ public class DefineProject extends VerticalLayout {
valider.setEnabled(true);
}
}
public void verifyToken(){
valider.setEnabled(true);
}
}

View file

@ -3,7 +3,9 @@ package org.chtijbug.drools.console.vaadincomponent.leftMenu.Action;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import org.chtijbug.drools.console.middle.JwtService;
import org.chtijbug.drools.console.service.ProjectPersistService;
import org.chtijbug.drools.console.service.UserConnectedService;
import org.chtijbug.drools.console.service.util.AppContext;
import org.chtijbug.drools.console.vaadincomponent.componentperso.DialogPerso;
import org.chtijbug.drools.console.vaadincomponent.Squelette.SqueletteComposant;

View file

@ -31,4 +31,7 @@ spring.servlet.multipart.max-request-size=100MB
# Server properties
server.tomcat.max-http-post-size=100000000
server.tomcat.max-swallow-size=100MB
server.tomcat.max-swallow-size=100MB
secretkey=eRaYY7Wo24sDqKSX3IM9ASGmdGPmkTd9jo1QTy4b7P9Ze5_9hKolVX8xNrQDcNRfVEdTZNOuOyqEGhXEbdJI-ZQ19k_o9MI0y3eZN2lp9jow55FfXMiINEdt1XR85VipRLSOkT6kSpzs2x-jbLDiz9iFVzkd81YKxMgPA7VfZeQUm4n-mOmnWMaVX30zGFU4L3oPBctYKkl4dYfqYWqRNfrgPJVi5DGFjywgxx0ASEiJHtV72paI3fDR2XwlSkyhhmY-ICjCRmsJN4fX1pdoL8a18-aQrvyu4j0Os6dVPYIoPvvY0SAZtWYKHfM15g7A3HD4cVREf9cUsprCRK93w