Skip to content

Commit

Permalink
chore: Update SSC/SC-SAST/SC-DAST session management
Browse files Browse the repository at this point in the history
fix: When authenticating with an SSC authentication token, the SSC, SC-SAST & SC-DAST session login commands will now validate whether the given token is a valid token

fix: When authenticating with an SSC authentication token, the SSC, SC-SAST & SC-DAST session commands will now display token expiration date (requires SSC 24.2+)
  • Loading branch information
rsenden committed Jul 26, 2024
1 parent aac8e10 commit c2e66bc
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@
import com.fortify.cli.ssc._common.session.helper.ISSCCredentialsConfig;
import com.fortify.cli.ssc._common.session.helper.ISSCUserCredentialsConfig;
import com.fortify.cli.ssc.access_control.helper.SSCTokenCreateRequest;
import com.fortify.cli.ssc.access_control.helper.SSCTokenCreateResponse;
import com.fortify.cli.ssc.access_control.helper.SSCTokenGetOrCreateResponse;
import com.fortify.cli.ssc.access_control.helper.SSCTokenHelper;
import com.fortify.cli.ssc.access_control.helper.SSCTokenCreateResponse.SSCTokenData;
import com.fortify.cli.ssc.access_control.helper.SSCTokenGetOrCreateResponse.SSCTokenData;

import kong.unirest.UnirestInstance;
import lombok.Data;
Expand All @@ -49,7 +49,7 @@ public class SCDastSessionDescriptor extends AbstractSessionDescriptor {
@JsonDeserialize(as = UrlConfig.class) private IUrlConfig sscUrlConfig;
@JsonDeserialize(as = UrlConfig.class) private IUrlConfig scDastUrlConfig;
private char[] predefinedToken;
private SSCTokenCreateResponse cachedTokenResponse;
private SSCTokenGetOrCreateResponse cachedTokenResponse;

public SCDastSessionDescriptor(IUrlConfig sscUrlConfig, ISSCCredentialsConfig credentialsConfig) {
this(sscUrlConfig, null, credentialsConfig);
Expand All @@ -58,7 +58,7 @@ public SCDastSessionDescriptor(IUrlConfig sscUrlConfig, ISSCCredentialsConfig cr
public SCDastSessionDescriptor(IUrlConfig sscUrlConfig, IUrlConfig scDastUrlConfig, ISSCCredentialsConfig credentialsConfig) {
this.sscUrlConfig = sscUrlConfig;
this.predefinedToken = credentialsConfig.getPredefinedToken();
this.cachedTokenResponse = generateToken(sscUrlConfig, credentialsConfig);
this.cachedTokenResponse = getOrGenerateToken(sscUrlConfig, credentialsConfig);
char[] activeToken = getActiveToken();
this.scDastUrlConfig = activeToken==null ? null : buildScDastUrlConfig(sscUrlConfig, scDastUrlConfig, activeToken);
}
Expand Down Expand Up @@ -106,17 +106,27 @@ public String getType() {
}

@JsonIgnore
protected SSCTokenCreateResponse generateToken(IUrlConfig urlConfig, ISSCCredentialsConfig credentialsConfig) {
if ( credentialsConfig.getPredefinedToken()==null ) {
ISSCUserCredentialsConfig uc = credentialsConfig.getUserCredentialsConfig();
if ( uc!=null && StringUtils.isNotBlank(uc.getUser()) && uc.getPassword()!=null ) {
SSCTokenCreateRequest tokenCreateRequest = SSCTokenCreateRequest.builder()
.description("Auto-generated by fcli session login command")
.terminalDate(getExpiresAt(uc.getExpiresAt()))
.type("CIToken")
.build();
return SSCTokenHelper.createToken(urlConfig, uc, tokenCreateRequest, SSCTokenCreateResponse.class);
}
protected SSCTokenGetOrCreateResponse getOrGenerateToken(IUrlConfig urlConfig, ISSCCredentialsConfig credentialsConfig) {
return credentialsConfig.getPredefinedToken()==null
? generateToken(urlConfig, credentialsConfig)
: getToken(urlConfig, credentialsConfig);
}

@JsonIgnore
protected SSCTokenGetOrCreateResponse getToken(IUrlConfig urlConfig, ISSCCredentialsConfig credentialsConfig) {
return SSCTokenHelper.getTokenData(urlConfig, credentialsConfig.getPredefinedToken());
}

@JsonIgnore
protected SSCTokenGetOrCreateResponse generateToken(IUrlConfig urlConfig, ISSCCredentialsConfig credentialsConfig) {
ISSCUserCredentialsConfig uc = credentialsConfig.getUserCredentialsConfig();
if ( uc!=null && StringUtils.isNotBlank(uc.getUser()) && uc.getPassword()!=null ) {
SSCTokenCreateRequest tokenCreateRequest = SSCTokenCreateRequest.builder()
.description("Auto-generated by fcli session login command")
.terminalDate(getExpiresAt(uc.getExpiresAt()))
.type("CIToken")
.build();
return SSCTokenHelper.createToken(urlConfig, uc, tokenCreateRequest, SSCTokenGetOrCreateResponse.class);
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@
import com.fortify.cli.ssc._common.session.helper.ISSCCredentialsConfig;
import com.fortify.cli.ssc._common.session.helper.ISSCUserCredentialsConfig;
import com.fortify.cli.ssc.access_control.helper.SSCTokenCreateRequest;
import com.fortify.cli.ssc.access_control.helper.SSCTokenCreateResponse;
import com.fortify.cli.ssc.access_control.helper.SSCTokenGetOrCreateResponse;
import com.fortify.cli.ssc.access_control.helper.SSCTokenHelper;
import com.fortify.cli.ssc.access_control.helper.SSCTokenCreateResponse.SSCTokenData;
import com.fortify.cli.ssc.access_control.helper.SSCTokenGetOrCreateResponse.SSCTokenData;

import kong.unirest.UnirestInstance;
import lombok.Data;
Expand All @@ -51,7 +51,7 @@ public class SCSastSessionDescriptor extends AbstractSessionDescriptor {
@JsonDeserialize(as = UrlConfig.class) private IUrlConfig scSastUrlConfig;
@Getter private char[] scSastClientAuthToken;
private char[] predefinedSscToken;
private SSCTokenCreateResponse cachedSscTokenResponse;
private SSCTokenGetOrCreateResponse cachedSscTokenResponse;

public SCSastSessionDescriptor(IUrlConfig sscUrlConfig, ISSCCredentialsConfig credentialsConfig, char[] scSastClientAuthToken) {
this(sscUrlConfig, null, credentialsConfig, scSastClientAuthToken);
Expand All @@ -61,7 +61,7 @@ public SCSastSessionDescriptor(IUrlConfig sscUrlConfig, IUrlConfig scSastUrlConf
this.sscUrlConfig = sscUrlConfig;
this.predefinedSscToken = credentialsConfig.getPredefinedToken();
this.scSastClientAuthToken = scSastClientAuthToken;
this.cachedSscTokenResponse = generateToken(sscUrlConfig, credentialsConfig);
this.cachedSscTokenResponse = getOrGenerateToken(sscUrlConfig, credentialsConfig);
char[] activeToken = getActiveSSCToken();
this.scSastUrlConfig = activeToken==null ? null : buildScSastUrlConfig(sscUrlConfig, scSastUrlConfig, activeToken);
}
Expand Down Expand Up @@ -110,17 +110,27 @@ public String getType() {
}

@JsonIgnore
protected SSCTokenCreateResponse generateToken(IUrlConfig urlConfig, ISSCCredentialsConfig credentialsConfig) {
if ( credentialsConfig.getPredefinedToken()==null ) {
ISSCUserCredentialsConfig uc = credentialsConfig.getUserCredentialsConfig();
if ( uc!=null && StringUtils.isNotBlank(uc.getUser()) && uc.getPassword()!=null ) {
SSCTokenCreateRequest tokenCreateRequest = SSCTokenCreateRequest.builder()
.description("Auto-generated by fcli session login command")
.terminalDate(getExpiresAt(uc.getExpiresAt()))
.type("UnifiedLoginToken")
.build();
return SSCTokenHelper.createToken(urlConfig, uc, tokenCreateRequest, SSCTokenCreateResponse.class);
}
protected SSCTokenGetOrCreateResponse getOrGenerateToken(IUrlConfig urlConfig, ISSCCredentialsConfig credentialsConfig) {
return credentialsConfig.getPredefinedToken()==null
? generateToken(urlConfig, credentialsConfig)
: getToken(urlConfig, credentialsConfig);
}

@JsonIgnore
protected SSCTokenGetOrCreateResponse getToken(IUrlConfig urlConfig, ISSCCredentialsConfig credentialsConfig) {
return SSCTokenHelper.getTokenData(urlConfig, credentialsConfig.getPredefinedToken());
}

@JsonIgnore
protected SSCTokenGetOrCreateResponse generateToken(IUrlConfig urlConfig, ISSCCredentialsConfig credentialsConfig) {
ISSCUserCredentialsConfig uc = credentialsConfig.getUserCredentialsConfig();
if ( uc!=null && StringUtils.isNotBlank(uc.getUser()) && uc.getPassword()!=null ) {
SSCTokenCreateRequest tokenCreateRequest = SSCTokenCreateRequest.builder()
.description("Auto-generated by fcli session login command")
.terminalDate(getExpiresAt(uc.getExpiresAt()))
.type("UnifiedLoginToken")
.build();
return SSCTokenHelper.createToken(urlConfig, uc, tokenCreateRequest, SSCTokenGetOrCreateResponse.class);
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
import com.fortify.cli.common.session.helper.SessionSummary;
import com.fortify.cli.common.util.StringUtils;
import com.fortify.cli.ssc.access_control.helper.SSCTokenCreateRequest;
import com.fortify.cli.ssc.access_control.helper.SSCTokenCreateResponse;
import com.fortify.cli.ssc.access_control.helper.SSCTokenCreateResponse.SSCTokenData;
import com.fortify.cli.ssc.access_control.helper.SSCTokenGetOrCreateResponse;
import com.fortify.cli.ssc.access_control.helper.SSCTokenGetOrCreateResponse.SSCTokenData;
import com.fortify.cli.ssc.access_control.helper.SSCTokenHelper;

import lombok.Data;
Expand All @@ -35,12 +35,12 @@
@Reflectable @NoArgsConstructor
public class SSCSessionDescriptor extends AbstractSessionDescriptorWithSingleUrlConfig {
private char[] predefinedToken;
private SSCTokenCreateResponse cachedTokenResponse;
private SSCTokenGetOrCreateResponse cachedTokenResponse;

public SSCSessionDescriptor(IUrlConfig urlConfig, ISSCCredentialsConfig credentialsConfig) {
super(urlConfig);
this.predefinedToken = credentialsConfig.getPredefinedToken();
this.cachedTokenResponse = generateToken(urlConfig, credentialsConfig);
this.cachedTokenResponse = getOrGenerateToken(urlConfig, credentialsConfig);
}

@JsonIgnore
Expand Down Expand Up @@ -74,17 +74,27 @@ public Date getExpiryDate() {
}

@JsonIgnore
protected SSCTokenCreateResponse generateToken(IUrlConfig urlConfig, ISSCCredentialsConfig credentialsConfig) {
if ( credentialsConfig.getPredefinedToken()==null ) {
ISSCUserCredentialsConfig uc = credentialsConfig.getUserCredentialsConfig();
if ( uc!=null && StringUtils.isNotBlank(uc.getUser()) && uc.getPassword()!=null ) {
SSCTokenCreateRequest tokenCreateRequest = SSCTokenCreateRequest.builder()
.description("Auto-generated by fcli session login command")
.terminalDate(uc.getExpiresAt())
.type("UnifiedLoginToken")
.build();
return SSCTokenHelper.createToken(urlConfig, uc, tokenCreateRequest, SSCTokenCreateResponse.class);
}
protected SSCTokenGetOrCreateResponse getOrGenerateToken(IUrlConfig urlConfig, ISSCCredentialsConfig credentialsConfig) {
return credentialsConfig.getPredefinedToken()==null
? generateToken(urlConfig, credentialsConfig)
: getToken(urlConfig, credentialsConfig);
}

@JsonIgnore
protected SSCTokenGetOrCreateResponse getToken(IUrlConfig urlConfig, ISSCCredentialsConfig credentialsConfig) {
return SSCTokenHelper.getTokenData(urlConfig, credentialsConfig.getPredefinedToken());
}

@JsonIgnore
protected SSCTokenGetOrCreateResponse generateToken(IUrlConfig urlConfig, ISSCCredentialsConfig credentialsConfig) {
ISSCUserCredentialsConfig uc = credentialsConfig.getUserCredentialsConfig();
if ( uc!=null && StringUtils.isNotBlank(uc.getUser()) && uc.getPassword()!=null ) {
SSCTokenCreateRequest tokenCreateRequest = SSCTokenCreateRequest.builder()
.description("Auto-generated by fcli session login command")
.terminalDate(uc.getExpiresAt())
.type("UnifiedLoginToken")
.build();
return SSCTokenHelper.createToken(urlConfig, uc, tokenCreateRequest, SSCTokenGetOrCreateResponse.class);
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
@Data
@Reflectable @NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public final class SSCTokenCreateResponse {
private SSCTokenCreateResponse.SSCTokenData data;
public final class SSCTokenGetOrCreateResponse {
private SSCTokenGetOrCreateResponse.SSCTokenData data;
@Data
@Reflectable @NoArgsConstructor
public static final class SSCTokenData {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.fortify.cli.common.http.proxy.helper.ProxyHelper;
import com.fortify.cli.common.json.JsonHelper;
import com.fortify.cli.common.rest.unirest.GenericUnirestFactory;
import com.fortify.cli.common.rest.unirest.UnexpectedHttpResponseException;
import com.fortify.cli.common.rest.unirest.config.IUrlConfig;
import com.fortify.cli.common.rest.unirest.config.IUserCredentialsConfig;
import com.fortify.cli.common.rest.unirest.config.UnirestBasicAuthConfigurer;
Expand Down Expand Up @@ -88,6 +89,12 @@ public static final <T> T createToken(IUrlConfig urlConfig, IUserCredentialsConf
}
}

public static final SSCTokenGetOrCreateResponse getTokenData(IUrlConfig urlConfig, char[] token) {
try ( var unirest = GenericUnirestFactory.createUnirestInstance() ) {
return getTokenData(unirest, urlConfig, token);
}
}

public static final <R> R run(IUrlConfig urlConfig, char[] activeToken, Function<UnirestInstance, R> f) {
try ( var unirest = GenericUnirestFactory.createUnirestInstance() ) {
configureUnirest(unirest, urlConfig, activeToken);
Expand Down Expand Up @@ -136,6 +143,25 @@ private static final <T> T createToken(UnirestInstance unirest, IUrlConfig urlCo
.getBody();
}

private static SSCTokenGetOrCreateResponse getTokenData(UnirestInstance unirest, IUrlConfig urlConfig, char[] token) {
configureUnirest(unirest, urlConfig, token);
try {
var result = unirest.post("/api/v1/userSession/tokenData")
.body(JsonHelper.getObjectMapper().createObjectNode())
.asObject(SSCTokenGetOrCreateResponse.class)
.getBody();
result.getData().setToken(token);
return result;
} catch ( UnexpectedHttpResponseException e ) {
if ( e.getStatus()==404 ) {
// Older SSC versions don't support this endpoint, so we just return null
return null;
} else {
throw e;
}
}
}

private static void configureUnirest(UnirestInstance unirest, IUrlConfig urlConfig, IUserCredentialsConfig uc) {
UnirestUnexpectedHttpResponseConfigurer.configure(unirest);
UnirestUrlConfigConfigurer.configure(unirest, urlConfig);
Expand Down

0 comments on commit c2e66bc

Please sign in to comment.