Skip to content

Commit

Permalink
Add new credentials type for the hub scc endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
mackdk authored and mcalmer committed Jan 21, 2025
1 parent 7cb4ffc commit ae12a13
Show file tree
Hide file tree
Showing 11 changed files with 210 additions and 35 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018--2024 SUSE LLC
* Copyright (c) 2018--2025 SUSE LLC
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
Expand Down Expand Up @@ -31,6 +31,7 @@
import com.redhat.rhn.domain.contentmgmt.SoftwareProjectSource;
import com.redhat.rhn.domain.credentials.BaseCredentials;
import com.redhat.rhn.domain.credentials.CloudRMTCredentials;
import com.redhat.rhn.domain.credentials.HubSCCCredentials;
import com.redhat.rhn.domain.credentials.RHUICredentials;
import com.redhat.rhn.domain.credentials.RegistryCredentials;
import com.redhat.rhn.domain.credentials.ReportDBCredentials;
Expand Down Expand Up @@ -194,6 +195,7 @@ private AnnotationRegistry() {
RHUICredentials.class,
SCCCredentials.class,
VHMCredentials.class,
HubSCCCredentials.class,
ChannelSyncFlag.class,
ServerCoCoAttestationConfig.class,
ServerCoCoAttestationReport.class,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
/*
* Copyright (c) 2012 SUSE LLC
* Copyright (c) 2012--2025 SUSE LLC
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/

package com.redhat.rhn.domain.credentials;
Expand Down Expand Up @@ -92,6 +88,17 @@ public static SCCCredentials createSCCCredentials(String username, String passwo
return new SCCCredentials(username, password);
}

/**
* Helper method for creating new Hub SCC {@link Credentials}
* @param username the username
* @param password the password that will be BASE64 encoded
* @param fqdn the FQDN of the peripheral server that will use this credentials
* @return new credential with type SCC
*/
public static HubSCCCredentials createHubSCCCredentials(String username, String password, String fqdn) {
return new HubSCCCredentials(username, password, fqdn);
}

/**
* Helper method for creating new Virtual Host Manager {@link Credentials}
* @param username the username
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
/*
* Copyright (c) 2012 SUSE LLC
* Copyright (c) 2012--2025 SUSE LLC
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package com.redhat.rhn.domain.credentials;

Expand All @@ -25,7 +21,8 @@ public enum CredentialsType {
REGISTRY(Label.REGISTRY),
CLOUD_RMT(Label.CLOUD_RMT),
REPORT_DATABASE(Label.REPORT_DATABASE),
RHUI(Label.RHUI);
RHUI(Label.RHUI),
HUB_SCC(Label.HUB_SCC);

private final String label;

Expand Down Expand Up @@ -58,6 +55,7 @@ public static class Label {
public static final String CLOUD_RMT = "cloudrmt";
public static final String REPORT_DATABASE = "reportcreds";
public static final String RHUI = "rhui";
public static final String HUB_SCC = "hub_scc";

private Label() {
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* Copyright (c) 2025 SUSE LLC
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*/

package com.redhat.rhn.domain.credentials;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;

import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.Transient;

@Entity
@DiscriminatorValue(CredentialsType.Label.HUB_SCC)
public class HubSCCCredentials extends PasswordBasedCredentials {

private String peripheralUrl;

// No args constructor for hibernate
protected HubSCCCredentials() {
}

// Default constructor filling the mandatory fields to be used in the CredentialFactory
protected HubSCCCredentials(String usernameIn, String passwordIn, String peripheralUrlIn) {
setUsername(usernameIn);
setPassword(passwordIn);
this.peripheralUrl = peripheralUrlIn;
}

@Override
@Transient
public CredentialsType getType() {
return CredentialsType.HUB_SCC;
}

@Column(name = "url")
public String getPeripheralUrl() {
return peripheralUrl;
}

public void setPeripheralUrl(String peripheralUrlIn) {
this.peripheralUrl = peripheralUrlIn;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}

if (!(o instanceof HubSCCCredentials that)) {
return false;
}

return new EqualsBuilder()
.appendSuper(super.equals(o))
.append(getPeripheralUrl(), that.getPeripheralUrl())
.isEquals();
}

@Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.appendSuper(super.hashCode())
.append(getPeripheralUrl())
.toHashCode();
}

@Override
public String toString() {
return new ToStringBuilder(this)
.append("id", getId())
.append("type", CredentialsType.HUB_SCC)
.append("user", getUser())
.append("username", getUsername())
.append("url", getPeripheralUrl())
.toString();
}
}
6 changes: 3 additions & 3 deletions java/code/src/com/suse/manager/iss/SyncController.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import static com.suse.manager.webui.utils.SparkApplicationHelper.success;
import static spark.Spark.post;

import com.redhat.rhn.domain.credentials.HubSCCCredentials;
import com.redhat.rhn.domain.iss.IssRole;

import com.suse.manager.model.hub.HubManager;
Expand Down Expand Up @@ -112,8 +113,8 @@ private String generateCredentials(Request request, Response response, Token tok
return badRequest(response, "Specified FQDN is not a known peripheral");
}

SCCCredentialsJson credentialsJson = hubManager.generateSCCCredentials(peripheral.getId());
return success(response, credentialsJson);
HubSCCCredentials credentials = hubManager.generateSCCCredentials(peripheral);
return success(response, new SCCCredentialsJson(credentials.getUsername(), credentials.getPassword()));
}

private String storeCredentials(Request request, Response response, Token token, String fqdn) {
Expand All @@ -126,7 +127,6 @@ private String storeCredentials(Request request, Response response, Token token,
}

hubManager.storeSCCCredentials(hub, storeRequest.getUsername(), storeRequest.getPassword());

return success(response);
}
}
29 changes: 17 additions & 12 deletions java/code/src/com/suse/manager/model/hub/HubManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import com.redhat.rhn.common.conf.ConfigDefaults;
import com.redhat.rhn.domain.credentials.CredentialsFactory;
import com.redhat.rhn.domain.credentials.HubSCCCredentials;
import com.redhat.rhn.domain.credentials.SCCCredentials;
import com.redhat.rhn.domain.iss.IssRole;
import com.redhat.rhn.domain.role.RoleFactory;
Expand Down Expand Up @@ -210,28 +211,30 @@ public void register(String remoteServer, IssRole role, String remoteToken, Stri

/**
* Generate SCC credentials for the specified peripheral
* @param peripheralId the id of the peripheral server
* @return the generated credentials
* @param peripheral the id of the peripheral server
* @return the generated {@link HubSCCCredentials}
*/
public SCCCredentialsJson generateSCCCredentials(long peripheralId) {
String username = "peripheral-%06d".formatted(peripheralId);
public HubSCCCredentials generateSCCCredentials(IssPeripheral peripheral) {
String username = "peripheral-%06d".formatted(peripheral.getId());
String password = RandomStringUtils.random(24, 0, 0, true, true, null, new SecureRandom());

/*
* TODO Store and return the credentials. This involves creating a new credential type not yet defined.
* For now, just return a SCCCredentialsJson object as temporary wrapper of username/password
*/
var hubSCCCredentials = CredentialsFactory.createHubSCCCredentials(username, password, peripheral.getFqdn());
CredentialsFactory.storeCredentials(hubSCCCredentials);

return new SCCCredentialsJson(username, password);
peripheral.setMirrorCredentials(hubSCCCredentials);
saveServer(peripheral);

return hubSCCCredentials;
}

/**
* Store the given SCC credentials into the credentials database
* @param hub the FQDN of the hub of this credentials
* @param username the username
* @param password the password
* @return the stored {@link SCCCredentials}
*/
public void storeSCCCredentials(IssHub hub, String username, String password) {
public SCCCredentials storeSCCCredentials(IssHub hub, String username, String password) {
// Delete any existing SCC Credentials
CredentialsFactory.listSCCCredentials()
.forEach(creds -> mirrorCredentialsManager.deleteMirrorCredentials(creds.getId(), null));
Expand All @@ -245,6 +248,8 @@ public void storeSCCCredentials(IssHub hub, String username, String password) {

hub.setMirrorCredentials(credentials);
saveServer(hub);

return credentials;
}

private void registerWithToken(String remoteServer, IssRole role, String rootCA, String remoteToken)
Expand All @@ -270,9 +275,9 @@ private void registerToRemote(IssServer remoteServer, String remoteToken, String

internalApi.register(localRoleForRemote, localAccessToken, localRootCA);

if (remoteServer instanceof IssPeripheral) {
if (remoteServer instanceof IssPeripheral peripheral) {
// if the remote server is a peripheral, generate the scc credentials for it
SCCCredentialsJson credentials = generateSCCCredentials(remoteServer.getId());
HubSCCCredentials credentials = generateSCCCredentials(peripheral);
internalApi.storeCredentials(credentials.getUsername(), credentials.getPassword());
}
else if (remoteServer instanceof IssHub hub) {
Expand Down
10 changes: 5 additions & 5 deletions java/code/src/com/suse/manager/model/hub/IssPeripheral.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
package com.suse.manager.model.hub;

import com.redhat.rhn.domain.BaseDomainHelper;
import com.redhat.rhn.domain.credentials.SCCCredentials;
import com.redhat.rhn.domain.credentials.HubSCCCredentials;
import com.redhat.rhn.domain.iss.IssRole;

import org.apache.commons.lang3.builder.HashCodeBuilder;
Expand All @@ -38,7 +38,7 @@ public class IssPeripheral extends BaseDomainHelper implements IssServer {
private Long id;
private String fqdn;
private String rootCa;
private SCCCredentials mirrorCredentials;
private HubSCCCredentials mirrorCredentials;
private Set<IssPeripheralChannels> peripheralChannels;

protected IssPeripheral() {
Expand Down Expand Up @@ -106,9 +106,9 @@ public String getRootCa() {
* Get the mirror credentials.
* @return the credentials
*/
@ManyToOne(targetEntity = SCCCredentials.class)
@ManyToOne(targetEntity = HubSCCCredentials.class)
@JoinColumn(name = "mirror_creds_id")
public SCCCredentials getMirrorCredentials() {
public HubSCCCredentials getMirrorCredentials() {
return mirrorCredentials;
}

Expand Down Expand Up @@ -146,7 +146,7 @@ public void setRootCa(String rootCaIn) {
/**
* @param mirrorCredentialsIn the mirror credentials
*/
public void setMirrorCredentials(SCCCredentials mirrorCredentialsIn) {
public void setMirrorCredentials(HubSCCCredentials mirrorCredentialsIn) {
mirrorCredentials = mirrorCredentialsIn;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.redhat.rhn.domain.channel.ChannelFactory;
import com.redhat.rhn.domain.channel.test.ChannelFactoryTest;
import com.redhat.rhn.domain.credentials.CredentialsFactory;
import com.redhat.rhn.domain.credentials.HubSCCCredentials;
import com.redhat.rhn.domain.credentials.SCCCredentials;
import com.redhat.rhn.testing.BaseTestCaseWithUser;
import com.redhat.rhn.testing.TestUtils;
Expand Down Expand Up @@ -96,7 +97,7 @@ public void testCreateIssPeripheral() {
assertNotNull(issPeripheral.get().getCreated(), "created should not be NULL");
assertNull(issPeripheral.get().getRootCa(), "Root CA should be NULL");

SCCCredentials sccCredentials = CredentialsFactory.createSCCCredentials("U123", "not so secret");
HubSCCCredentials sccCredentials = CredentialsFactory.createHubSCCCredentials("U123", "not so secret", "fqdn");
CredentialsFactory.storeCredentials(sccCredentials);

peripheral.setRootCa("----- BEGIN CA -----");
Expand All @@ -112,7 +113,7 @@ public void testCreateIssPeripheral() {

@Test
public void testCreateIssPeripheralChannels() throws Exception {
SCCCredentials sccCredentials = CredentialsFactory.createSCCCredentials("U123", "not so secret");
HubSCCCredentials sccCredentials = CredentialsFactory.createHubSCCCredentials("U123", "not so secret", "fqdn");
CredentialsFactory.storeCredentials(sccCredentials);

Channel baseChannel = ChannelFactoryTest.createBaseChannel(user);
Expand Down
33 changes: 33 additions & 0 deletions java/code/src/com/suse/manager/model/hub/test/HubManagerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.redhat.rhn.common.conf.Config;
import com.redhat.rhn.common.conf.ConfigDefaults;
import com.redhat.rhn.domain.credentials.CredentialsFactory;
import com.redhat.rhn.domain.credentials.HubSCCCredentials;
import com.redhat.rhn.domain.credentials.SCCCredentials;
import com.redhat.rhn.domain.iss.IssRole;
import com.redhat.rhn.manager.setup.MirrorCredentialsManager;
Expand Down Expand Up @@ -277,6 +278,38 @@ public void canUpdateServer() {
assertEquals("password", issHub.get().getMirrorCredentials().getPassword());
}

@Test
public void canGenerateSCCCredentials() {
String peripheralFqdn = "dummy.peripheral.fqdn";

var peripheral = (IssPeripheral) hubManager.saveNewServer(IssRole.PERIPHERAL, peripheralFqdn, null);

// Ensure no credentials exists
assertEquals(0, CredentialsFactory.listCredentialsByType(HubSCCCredentials.class).stream()
.filter(creds -> peripheralFqdn.equals(creds.getPeripheralUrl()))
.count());

HubSCCCredentials hubSCCCredentials = hubManager.generateSCCCredentials(peripheral);
assertEquals("peripheral-%06d".formatted(peripheral.getId()), hubSCCCredentials.getUsername());
assertNotNull(hubSCCCredentials.getPassword());
assertEquals(peripheralFqdn, hubSCCCredentials.getPeripheralUrl());
}

@Test
public void canStoreSCCCredentials() {
String hubFqdn = "dummy.hub.fqdn";
var hub = (IssHub) hubManager.saveNewServer(IssRole.HUB, hubFqdn, null);

// Ensure no credentials exists
assertEquals(0, CredentialsFactory.listSCCCredentials().stream()
.filter(creds -> "https://dummy.hub.fqdn".equals(creds.getUrl()))
.count());

SCCCredentials sccCredentials = hubManager.storeSCCCredentials(hub, "dummy-username", "dummy-password");
assertEquals("dummy-username", sccCredentials.getUsername());
assertEquals("dummy-password", sccCredentials.getPassword());
assertEquals("https://dummy.hub.fqdn", sccCredentials.getUrl());
}

@Test
public void canRegisterPeripheralWithUserNameAndPassword()
Expand Down
Loading

0 comments on commit ae12a13

Please sign in to comment.