From 5ed5b67c326e145871ecab87c254393b2955bb92 Mon Sep 17 00:00:00 2001 From: entholzer Date: Wed, 4 Dec 2024 22:09:29 +0100 Subject: [PATCH 1/7] resolve merge issues --- .../ssh/SshFingerprintsProviderService.java | 50 ++++++++++++ .../ssh/SshFingerprintsProviderResource.java | 44 +++++++++++ ...-user-settings-fingerprints.component.html | 56 ++++++++++++++ ...-user-settings-fingerprints.component.scss | 12 +++ ...sh-user-settings-fingerprints.component.ts | 24 ++++++ .../ssh-user-settings-fingerprints.service.ts | 14 ++++ .../ssh-user-settings.component.html | 7 +- .../user-settings/user-settings.module.ts | 2 + .../user-settings/user-settings.route.ts | 8 ++ src/main/webapp/i18n/de/userSettings.json | 4 + src/main/webapp/i18n/en/userSettings.json | 4 + ...shFingerprintsProviderIntegrationTest.java | 77 +++++++++++++++++++ ...er-settings-fingerprints.component.spec.ts | 44 +++++++++++ ...ser-settings-key-details.component.spec.ts | 8 +- .../ssh-user-settings.component.spec.ts | 4 +- ...user-settings-fingerprints.service.spec.ts | 29 +++++++ 16 files changed, 380 insertions(+), 7 deletions(-) create mode 100644 src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/SshFingerprintsProviderService.java create mode 100644 src/main/java/de/tum/cit/aet/artemis/programming/web/localvc/ssh/SshFingerprintsProviderResource.java create mode 100644 src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.html create mode 100644 src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.scss create mode 100644 src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.ts create mode 100644 src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.service.ts create mode 100644 src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderIntegrationTest.java create mode 100644 src/test/javascript/spec/component/account/ssh/ssh-user-settings-fingerprints.component.spec.ts rename src/test/javascript/spec/component/account/{ => ssh}/ssh-user-settings-key-details.component.spec.ts (94%) rename src/test/javascript/spec/component/account/{ => ssh}/ssh-user-settings.component.spec.ts (95%) create mode 100644 src/test/javascript/spec/service/ssh-user-settings-fingerprints.service.spec.ts diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/SshFingerprintsProviderService.java b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/SshFingerprintsProviderService.java new file mode 100644 index 000000000000..5d1db5b15e73 --- /dev/null +++ b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/SshFingerprintsProviderService.java @@ -0,0 +1,50 @@ +package de.tum.cit.aet.artemis.programming.service.localvc.ssh; + +import static de.tum.cit.aet.artemis.core.config.Constants.PROFILE_LOCALVC; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.util.HashMap; +import java.util.Map; + +import jakarta.ws.rs.BadRequestException; + +import org.apache.sshd.common.keyprovider.KeyPairProvider; +import org.apache.sshd.server.SshServer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +/** + * This class configures the JGit Servlet, which is used to receive Git push and fetch requests for local VC. + */ +@Profile(PROFILE_LOCALVC) +@Service +public class SshFingerprintsProviderService { + + private static final Logger log = LoggerFactory.getLogger(SshFingerprintsProviderService.class); + + private final SshServer sshServer; + + public SshFingerprintsProviderService(SshServer sshServer) { + this.sshServer = sshServer; + } + + public Map getSshFingerPrints() { + Map fingerprints = new HashMap<>(); + KeyPairProvider keyPairProvider = sshServer.getKeyPairProvider(); + if (keyPairProvider != null) { + try { + keyPairProvider.loadKeys(null).iterator() + .forEachRemaining(keyPair -> fingerprints.put(keyPair.getPublic().getAlgorithm(), HashUtils.getSha512Fingerprint(keyPair.getPublic()))); + + } + catch (IOException | GeneralSecurityException e) { + log.info("Could not load keys from the ssh server while trying to get SSH key fingerprints", e); + throw new BadRequestException("Could not load keys from the ssh server"); + } + } + return fingerprints; + } +} diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/web/localvc/ssh/SshFingerprintsProviderResource.java b/src/main/java/de/tum/cit/aet/artemis/programming/web/localvc/ssh/SshFingerprintsProviderResource.java new file mode 100644 index 000000000000..eaaf3d345fb7 --- /dev/null +++ b/src/main/java/de/tum/cit/aet/artemis/programming/web/localvc/ssh/SshFingerprintsProviderResource.java @@ -0,0 +1,44 @@ +package de.tum.cit.aet.artemis.programming.web.localvc.ssh; + +import static de.tum.cit.aet.artemis.core.config.Constants.PROFILE_LOCALVC; + +import java.util.Map; + +import org.springframework.context.annotation.Profile; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import de.tum.cit.aet.artemis.core.security.annotations.EnforceAtLeastStudent; +import de.tum.cit.aet.artemis.core.service.feature.Feature; +import de.tum.cit.aet.artemis.core.service.feature.FeatureToggle; +import de.tum.cit.aet.artemis.programming.service.localvc.ssh.SshFingerprintsProviderService; + +/** + * REST controller for managing. + */ +@Profile(PROFILE_LOCALVC) +@RestController +@RequestMapping("api/") +public class SshFingerprintsProviderResource { + + SshFingerprintsProviderService sshFingerprintsProviderService; + + public SshFingerprintsProviderResource(SshFingerprintsProviderService sshFingerprintsProviderService) { + this.sshFingerprintsProviderService = sshFingerprintsProviderService; + } + + /** + * GET /ssh-fingerprints + * + * @return the SSH fingerprints for the keys a user uses + */ + @GetMapping(value = "ssh-fingerprints", produces = MediaType.APPLICATION_JSON_VALUE) + @EnforceAtLeastStudent + @FeatureToggle(Feature.Exports) + public ResponseEntity> getSshFingerprints() { + return ResponseEntity.ok().body(sshFingerprintsProviderService.getSshFingerPrints()); + } +} diff --git a/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.html b/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.html new file mode 100644 index 000000000000..44df3d891ced --- /dev/null +++ b/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.html @@ -0,0 +1,56 @@ +

+ +
+ +
+
+

+ + + +

+
+ + @if (sshFingerprints && sshFingerprints['RSA']) { +
+
+ {{ 'RSA' }} +
+
+ {{ sshFingerprints['RSA'] }} +
+
+ } + + @if (sshFingerprints && sshFingerprints['ED25519']) { +
+
+ {{ 'ED25519' }} +
+
+ {{ sshFingerprints['ED25519'] }} +
+
+ } + + @if (sshFingerprints && sshFingerprints['ECDSA']) { +
+
+ {{ 'ECDSA' }} +
+
+ {{ sshFingerprints['ECDSA'] }} +
+
+ } + +
+
+
+ + + +
+
+
+
diff --git a/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.scss b/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.scss new file mode 100644 index 000000000000..61b3ac821994 --- /dev/null +++ b/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.scss @@ -0,0 +1,12 @@ +.column { + float: left; + padding: 10px; +} + +.left { + width: 15%; +} + +.right { + width: 85%; +} diff --git a/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.ts b/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.ts new file mode 100644 index 000000000000..52e8676bb456 --- /dev/null +++ b/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.ts @@ -0,0 +1,24 @@ +import { Component, OnInit, inject } from '@angular/core'; +import { ButtonSize, ButtonType } from 'app/shared/components/button.component'; +import { DocumentationType } from 'app/shared/components/documentation-button/documentation-button.component'; +import { SshUserSettingsFingerprintsService } from 'app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.service'; + +@Component({ + selector: 'jhi-account-information', + templateUrl: './ssh-user-settings-fingerprints.component.html', + styleUrls: ['./ssh-user-settings-fingerprints.component.scss', '../ssh-user-settings.component.scss'], +}) +export class SshUserSettingsFingerprintsComponent implements OnInit { + readonly sshUserSettingsService = inject(SshUserSettingsFingerprintsService); + + protected sshFingerprints?: { [key: string]: string }; + + readonly documentationType: DocumentationType = 'SshSetup'; + protected readonly ButtonType = ButtonType; + + protected readonly ButtonSize = ButtonSize; + + async ngOnInit() { + this.sshFingerprints = await this.sshUserSettingsService.getSshFingerprints(); + } +} diff --git a/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.service.ts b/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.service.ts new file mode 100644 index 000000000000..ac14ef15666d --- /dev/null +++ b/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.service.ts @@ -0,0 +1,14 @@ +import { Injectable, inject } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { firstValueFrom } from 'rxjs'; + +@Injectable({ providedIn: 'root' }) +export class SshUserSettingsFingerprintsService { + error?: string; + + private http = inject(HttpClient); + + public async getSshFingerprints(): Promise<{ [key: string]: string }> { + return await firstValueFrom(this.http.get<{ [key: string]: string }>('api/ssh-fingerprints')); + } +} diff --git a/src/main/webapp/app/shared/user-settings/ssh-settings/ssh-user-settings.component.html b/src/main/webapp/app/shared/user-settings/ssh-settings/ssh-user-settings.component.html index a5650cef05a9..be96fb1808f4 100644 --- a/src/main/webapp/app/shared/user-settings/ssh-settings/ssh-user-settings.component.html +++ b/src/main/webapp/app/shared/user-settings/ssh-settings/ssh-user-settings.component.html @@ -27,7 +27,7 @@

-
+

@@ -103,6 +103,11 @@

+
+ + + +
diff --git a/src/main/webapp/app/shared/user-settings/user-settings.module.ts b/src/main/webapp/app/shared/user-settings/user-settings.module.ts index 11c876830750..e9c2ed73395e 100644 --- a/src/main/webapp/app/shared/user-settings/user-settings.module.ts +++ b/src/main/webapp/app/shared/user-settings/user-settings.module.ts @@ -13,6 +13,7 @@ import { FormDateTimePickerModule } from 'app/shared/date-time-picker/date-time- import { IdeSettingsComponent } from 'app/shared/user-settings/ide-preferences/ide-settings.component'; import { DocumentationLinkComponent } from 'app/shared/components/documentation-link/documentation-link.component'; import { SshUserSettingsKeyDetailsComponent } from 'app/shared/user-settings/ssh-settings/details/ssh-user-settings-key-details.component'; +import { SshUserSettingsFingerprintsComponent } from 'app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component'; @NgModule({ imports: [RouterModule.forChild(userSettingsState), ArtemisSharedModule, ArtemisSharedComponentModule, ClipboardModule, FormDateTimePickerModule, DocumentationLinkComponent], @@ -22,6 +23,7 @@ import { SshUserSettingsKeyDetailsComponent } from 'app/shared/user-settings/ssh ScienceSettingsComponent, SshUserSettingsComponent, SshUserSettingsKeyDetailsComponent, + SshUserSettingsFingerprintsComponent, VcsAccessTokensSettingsComponent, IdeSettingsComponent, ], diff --git a/src/main/webapp/app/shared/user-settings/user-settings.route.ts b/src/main/webapp/app/shared/user-settings/user-settings.route.ts index 41d8a2084df7..cbd0278d3bde 100644 --- a/src/main/webapp/app/shared/user-settings/user-settings.route.ts +++ b/src/main/webapp/app/shared/user-settings/user-settings.route.ts @@ -9,6 +9,7 @@ import { SshUserSettingsComponent } from 'app/shared/user-settings/ssh-settings/ import { VcsAccessTokensSettingsComponent } from 'app/shared/user-settings/vcs-access-tokens-settings/vcs-access-tokens-settings.component'; import { IdeSettingsComponent } from 'app/shared/user-settings/ide-preferences/ide-settings.component'; import { SshUserSettingsKeyDetailsComponent } from 'app/shared/user-settings/ssh-settings/details/ssh-user-settings-key-details.component'; +import { SshUserSettingsFingerprintsComponent } from 'app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component'; export const userSettingsState: Routes = [ { @@ -60,6 +61,13 @@ export const userSettingsState: Routes = [ pageTitle: 'artemisApp.userSettings.categories.SSH_SETTINGS', }, }, + { + path: 'ssh/fingerprints', + component: SshUserSettingsFingerprintsComponent, + data: { + pageTitle: 'artemisApp.userSettings.categories.SSH_SETTINGS', + }, + }, { path: 'ssh/view/:keyId', component: SshUserSettingsKeyDetailsComponent, diff --git a/src/main/webapp/i18n/de/userSettings.json b/src/main/webapp/i18n/de/userSettings.json index 4d08bc1abb0d..84953e9f1707 100644 --- a/src/main/webapp/i18n/de/userSettings.json +++ b/src/main/webapp/i18n/de/userSettings.json @@ -55,6 +55,10 @@ "expiresOn": "Läuft ab am", "hasExpiredOn": "Abgelaufen am", "fingerprint": "Fingerabdruck", + "fingerprints": "Fingerabdrücke", + "sshFingerprints": "SSH Fingerabdrücke", + "fingerprintsExplanation": "Mit SSH-Schlüsseln kannst du eine sichere Verbindung zwischen deinem Computer und Artemis herstellen. SSH-Fingerabdrücke stellen sicher, dass der Client eine Verbindung zum richtigen Host herstellt.", + "fingerprintsLearnMore": "Lerne mehr über Fingerabdrücke", "commentUsedAsLabel": "Wenn du kein Label hinzufügst, wird der Schlüsselkommentar (sofern vorhanden) als Label verwendet.", "expiry": { "title": "Ablauf", diff --git a/src/main/webapp/i18n/en/userSettings.json b/src/main/webapp/i18n/en/userSettings.json index c42a5c7b1ac3..5bf3c30161da 100644 --- a/src/main/webapp/i18n/en/userSettings.json +++ b/src/main/webapp/i18n/en/userSettings.json @@ -55,6 +55,10 @@ "expiresOn": "Expires on", "hasExpiredOn": "Expired on", "fingerprint": "Fingerprint", + "fingerprints": "Fingerprints", + "sshFingerprints": "SSH Fingerprints", + "fingerprintsExplanation": "SSH keys allow you to establish a secure connection between your computer and Artemis. SSH fingerprints verify that the client is connecting to the correct host.", + "fingerprintsLearnMore": "Learn more about fingerprints", "commentUsedAsLabel": "If you do not add a label, the key comment will be used as the default label if present.", "expiry": { "title": "Expiry", diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderIntegrationTest.java new file mode 100644 index 000000000000..7eb80589dfc4 --- /dev/null +++ b/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderIntegrationTest.java @@ -0,0 +1,77 @@ +package de.tum.cit.aet.artemis.programming.icl; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; + +import java.io.IOException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.util.Collections; +import java.util.Map; + +import org.apache.sshd.common.keyprovider.KeyPairProvider; +import org.apache.sshd.server.SshServer; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.HttpStatus; +import org.springframework.security.test.context.support.WithMockUser; + +import de.tum.cit.aet.artemis.programming.service.localvc.ssh.HashUtils; +import de.tum.cit.aet.artemis.shared.base.AbstractSpringIntegrationLocalCILocalVCTest; + +public class SshFingerprintsProviderIntegrationTest extends AbstractSpringIntegrationLocalCILocalVCTest { + + private static final String TEST_PREFIX = "sshFingerprintsTest"; + + @MockBean + private SshServer sshServer; + + @Mock + private KeyPairProvider keyPairProvider; + + private String expectedFingerprint; + + @BeforeEach + void setup() throws Exception { + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); + keyPairGenerator.initialize(2048); + KeyPair testKeyPair = keyPairGenerator.generateKeyPair(); + + expectedFingerprint = HashUtils.getSha512Fingerprint(testKeyPair.getPublic()); + doReturn(keyPairProvider).when(sshServer).getKeyPairProvider(); + doReturn(Collections.singleton(testKeyPair)).when(keyPairProvider).loadKeys(null); + } + + @Nested + class SshFingerprintsProvider { + + @Test + @WithMockUser(username = TEST_PREFIX + "student1", roles = "USER") + void shouldReturnFingerprints() throws Exception { + var response = request.get("/api/ssh-fingerprints", HttpStatus.OK, Map.class); + assertThat(response.get("RSA")).isNotNull(); + assertThat(response.get("RSA")).isEqualTo(expectedFingerprint); + } + + @Test + @WithMockUser(username = TEST_PREFIX + "student1", roles = "USER") + void shouldReturnNoFingerprintsWithoutKeyProviderSetup() throws Exception { + doReturn(null).when(sshServer).getKeyPairProvider(); + + var response = request.get("/api/ssh-fingerprints", HttpStatus.OK, Map.class); + assertThat(response.isEmpty()).isTrue(); + } + + @Test + @WithMockUser(username = TEST_PREFIX + "student1", roles = "USER") + void shouldReturnBadRequestWhenLoadKeysThrowsException() throws Exception { + doThrow(new IOException("Test exception")).when(keyPairProvider).loadKeys(null); + + request.get("/api/ssh-fingerprints", HttpStatus.BAD_REQUEST, Map.class); + } + } +} diff --git a/src/test/javascript/spec/component/account/ssh/ssh-user-settings-fingerprints.component.spec.ts b/src/test/javascript/spec/component/account/ssh/ssh-user-settings-fingerprints.component.spec.ts new file mode 100644 index 000000000000..dc27cccd101c --- /dev/null +++ b/src/test/javascript/spec/component/account/ssh/ssh-user-settings-fingerprints.component.spec.ts @@ -0,0 +1,44 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ArtemisTestModule } from '../../../test.module'; +import { TranslatePipeMock } from '../../../helpers/mocks/service/mock-translate.service'; +import { TranslateService } from '@ngx-translate/core'; +import { SshUserSettingsFingerprintsComponent } from 'app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component'; +import { SshUserSettingsFingerprintsService } from 'app/shared/user-settings/ssh-settings/ssh-user-settings.service'; + +describe('SshUserSettingsFingerprintsComponent', () => { + let fixture: ComponentFixture; + let comp: SshUserSettingsFingerprintsComponent; + const mockFingerprints: { [key: string]: string } = { + RSA: 'SHA512:abcde123', + }; + + let fingerPintsServiceMock: { + getSshFingerprints: jest.Mock; + }; + let translateService: TranslateService; + + beforeEach(async () => { + fingerPintsServiceMock = { + getSshFingerprints: jest.fn(), + }; + jest.spyOn(console, 'error').mockImplementation(() => {}); + await TestBed.configureTestingModule({ + imports: [ArtemisTestModule], + declarations: [SshUserSettingsFingerprintsComponent, TranslatePipeMock], + providers: [{ provide: SshUserSettingsFingerprintsService, useValue: fingerPintsServiceMock }], + }).compileComponents(); + fixture = TestBed.createComponent(SshUserSettingsFingerprintsComponent); + comp = fixture.componentInstance; + translateService = TestBed.inject(TranslateService); + translateService.currentLang = 'en'; + + fingerPintsServiceMock.getSshFingerprints.mockImplementation(() => Promise.resolve(mockFingerprints)); + }); + + it('should display fingerprints', async () => { + await comp.ngOnInit(); + await fixture.whenStable(); + + expect(fingerPintsServiceMock.getSshFingerprints).toHaveBeenCalled(); + }); +}); diff --git a/src/test/javascript/spec/component/account/ssh-user-settings-key-details.component.spec.ts b/src/test/javascript/spec/component/account/ssh/ssh-user-settings-key-details.component.spec.ts similarity index 94% rename from src/test/javascript/spec/component/account/ssh-user-settings-key-details.component.spec.ts rename to src/test/javascript/spec/component/account/ssh/ssh-user-settings-key-details.component.spec.ts index aaf82ea0c2e5..7db9e8fb4d9d 100644 --- a/src/test/javascript/spec/component/account/ssh-user-settings-key-details.component.spec.ts +++ b/src/test/javascript/spec/component/account/ssh/ssh-user-settings-key-details.component.spec.ts @@ -2,13 +2,13 @@ import { HttpErrorResponse } from '@angular/common/http'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { of, throwError } from 'rxjs'; import { ActivatedRoute, Router } from '@angular/router'; -import { ArtemisTestModule } from '../../test.module'; -import { MockNgbModalService } from '../../helpers/mocks/service/mock-ngb-modal.service'; -import { MockTranslateService, TranslatePipeMock } from '../../helpers/mocks/service/mock-translate.service'; +import { ArtemisTestModule } from '../../../test.module'; +import { MockNgbModalService } from '../../../helpers/mocks/service/mock-ngb-modal.service'; +import { MockTranslateService, TranslatePipeMock } from '../../../helpers/mocks/service/mock-translate.service'; import { TranslateService } from '@ngx-translate/core'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { SshUserSettingsKeyDetailsComponent } from 'app/shared/user-settings/ssh-settings/details/ssh-user-settings-key-details.component'; -import { MockActivatedRoute } from '../../helpers/mocks/activated-route/mock-activated-route'; +import { MockActivatedRoute } from '../../../helpers/mocks/activated-route/mock-activated-route'; import { UserSshPublicKey } from 'app/entities/programming/user-ssh-public-key.model'; import dayjs from 'dayjs/esm'; import { AlertService } from 'app/core/util/alert.service'; diff --git a/src/test/javascript/spec/component/account/ssh-user-settings.component.spec.ts b/src/test/javascript/spec/component/account/ssh/ssh-user-settings.component.spec.ts similarity index 95% rename from src/test/javascript/spec/component/account/ssh-user-settings.component.spec.ts rename to src/test/javascript/spec/component/account/ssh/ssh-user-settings.component.spec.ts index fe6a9304c68c..ab214751c27a 100644 --- a/src/test/javascript/spec/component/account/ssh-user-settings.component.spec.ts +++ b/src/test/javascript/spec/component/account/ssh/ssh-user-settings.component.spec.ts @@ -1,8 +1,8 @@ import { HttpResponse } from '@angular/common/http'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { of, throwError } from 'rxjs'; -import { ArtemisTestModule } from '../../test.module'; -import { MockTranslateService, TranslatePipeMock } from '../../helpers/mocks/service/mock-translate.service'; +import { ArtemisTestModule } from '../../../test.module'; +import { MockTranslateService, TranslatePipeMock } from '../../../helpers/mocks/service/mock-translate.service'; import { TranslateService } from '@ngx-translate/core'; import { SshUserSettingsComponent } from 'app/shared/user-settings/ssh-settings/ssh-user-settings.component'; import { UserSshPublicKey } from 'app/entities/programming/user-ssh-public-key.model'; diff --git a/src/test/javascript/spec/service/ssh-user-settings-fingerprints.service.spec.ts b/src/test/javascript/spec/service/ssh-user-settings-fingerprints.service.spec.ts new file mode 100644 index 000000000000..f461ca9599d0 --- /dev/null +++ b/src/test/javascript/spec/service/ssh-user-settings-fingerprints.service.spec.ts @@ -0,0 +1,29 @@ +import { TestBed, fakeAsync } from '@angular/core/testing'; +import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; +import { provideHttpClient } from '@angular/common/http'; +import { SshUserSettingsFingerprintsService } from 'app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.service'; + +describe('SshUserSettingsFingerprintsService', () => { + let sshFingerprintsService: SshUserSettingsFingerprintsService; + let httpMock: HttpTestingController; + + const getUserUrl = 'api/ssh-fingerprints'; + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [provideHttpClient(), provideHttpClientTesting()], + }); + sshFingerprintsService = TestBed.inject(SshUserSettingsFingerprintsService); + httpMock = TestBed.inject(HttpTestingController); + }); + + afterEach(() => { + httpMock.verify(); + jest.restoreAllMocks(); + }); + + it('should get SSH fingerprints', fakeAsync(() => { + sshFingerprintsService.getSshFingerprints(); + httpMock.expectOne({ method: 'GET', url: getUserUrl }); + })); +}); From ac24f795782079d3f155819cdef66802a563cc9c Mon Sep 17 00:00:00 2001 From: entholzer Date: Thu, 5 Dec 2024 07:42:49 +0100 Subject: [PATCH 2/7] changed to SHA:256 to use it in shell --- .../artemis/programming/service/localvc/ssh/HashUtils.java | 4 ++++ .../service/localvc/ssh/SshFingerprintsProviderService.java | 2 +- .../ssh-user-settings-fingerprints.component.html | 4 ++-- .../fingerprints/ssh-user-settings-fingerprints.component.ts | 1 + 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/HashUtils.java b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/HashUtils.java index 4312a3b45789..0ca141ed9f60 100644 --- a/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/HashUtils.java +++ b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/HashUtils.java @@ -10,4 +10,8 @@ public class HashUtils { public static String getSha512Fingerprint(PublicKey key) { return KeyUtils.getFingerPrint(BuiltinDigests.sha512.create(), key); } + + public static String getSha256Fingerprint(PublicKey key) { + return KeyUtils.getFingerPrint(BuiltinDigests.sha256.create(), key); + } } diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/SshFingerprintsProviderService.java b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/SshFingerprintsProviderService.java index 5d1db5b15e73..63cf84d33ae3 100644 --- a/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/SshFingerprintsProviderService.java +++ b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/SshFingerprintsProviderService.java @@ -37,7 +37,7 @@ public Map getSshFingerPrints() { if (keyPairProvider != null) { try { keyPairProvider.loadKeys(null).iterator() - .forEachRemaining(keyPair -> fingerprints.put(keyPair.getPublic().getAlgorithm(), HashUtils.getSha512Fingerprint(keyPair.getPublic()))); + .forEachRemaining(keyPair -> fingerprints.put(keyPair.getPublic().getAlgorithm(), HashUtils.getSha256Fingerprint(keyPair.getPublic()))); } catch (IOException | GeneralSecurityException e) { diff --git a/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.html b/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.html index 44df3d891ced..b19433bc9069 100644 --- a/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.html +++ b/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.html @@ -22,13 +22,13 @@

} - @if (sshFingerprints && sshFingerprints['ED25519']) { + @if (sshFingerprints && sshFingerprints['EdDSA']) {
{{ 'ED25519' }}
- {{ sshFingerprints['ED25519'] }} + {{ sshFingerprints['EdDSA'] }}
} diff --git a/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.ts b/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.ts index 52e8676bb456..39fa756bd126 100644 --- a/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.ts +++ b/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.ts @@ -20,5 +20,6 @@ export class SshUserSettingsFingerprintsComponent implements OnInit { async ngOnInit() { this.sshFingerprints = await this.sshUserSettingsService.getSshFingerprints(); + console.log(this.sshFingerprints); } } From 6ec63ce01f7874d4267607744762a1ce9ddf47a3 Mon Sep 17 00:00:00 2001 From: entholzer Date: Thu, 5 Dec 2024 08:00:21 +0100 Subject: [PATCH 3/7] fix javadoc --- .../service/localvc/ssh/SshFingerprintsProviderService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/SshFingerprintsProviderService.java b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/SshFingerprintsProviderService.java index 63cf84d33ae3..ff2e7c99e324 100644 --- a/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/SshFingerprintsProviderService.java +++ b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/SshFingerprintsProviderService.java @@ -17,7 +17,7 @@ import org.springframework.stereotype.Service; /** - * This class configures the JGit Servlet, which is used to receive Git push and fetch requests for local VC. + * Service responsible for providing SSH fingerprints of the SSH server running in Artemis. */ @Profile(PROFILE_LOCALVC) @Service From 785a69155028e5ba2eab032366b736aa9dc2d6f5 Mon Sep 17 00:00:00 2001 From: entholzer Date: Thu, 5 Dec 2024 08:03:02 +0100 Subject: [PATCH 4/7] fix tests --- .../programming/icl/SshFingerprintsProviderIntegrationTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderIntegrationTest.java index 7eb80589dfc4..f81b94d5f386 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderIntegrationTest.java @@ -41,7 +41,7 @@ void setup() throws Exception { keyPairGenerator.initialize(2048); KeyPair testKeyPair = keyPairGenerator.generateKeyPair(); - expectedFingerprint = HashUtils.getSha512Fingerprint(testKeyPair.getPublic()); + expectedFingerprint = HashUtils.getSha256Fingerprint(testKeyPair.getPublic()); doReturn(keyPairProvider).when(sshServer).getKeyPairProvider(); doReturn(Collections.singleton(testKeyPair)).when(keyPairProvider).loadKeys(null); } From 41aae09720697492e004e673c287f3ee2c9ec68f Mon Sep 17 00:00:00 2001 From: entholzer Date: Thu, 5 Dec 2024 08:06:46 +0100 Subject: [PATCH 5/7] remove console log --- .../fingerprints/ssh-user-settings-fingerprints.component.ts | 1 - .../ssh/ssh-user-settings-fingerprints.component.spec.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.ts b/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.ts index 39fa756bd126..52e8676bb456 100644 --- a/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.ts +++ b/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.ts @@ -20,6 +20,5 @@ export class SshUserSettingsFingerprintsComponent implements OnInit { async ngOnInit() { this.sshFingerprints = await this.sshUserSettingsService.getSshFingerprints(); - console.log(this.sshFingerprints); } } diff --git a/src/test/javascript/spec/component/account/ssh/ssh-user-settings-fingerprints.component.spec.ts b/src/test/javascript/spec/component/account/ssh/ssh-user-settings-fingerprints.component.spec.ts index dc27cccd101c..c1935aa3cf67 100644 --- a/src/test/javascript/spec/component/account/ssh/ssh-user-settings-fingerprints.component.spec.ts +++ b/src/test/javascript/spec/component/account/ssh/ssh-user-settings-fingerprints.component.spec.ts @@ -3,7 +3,7 @@ import { ArtemisTestModule } from '../../../test.module'; import { TranslatePipeMock } from '../../../helpers/mocks/service/mock-translate.service'; import { TranslateService } from '@ngx-translate/core'; import { SshUserSettingsFingerprintsComponent } from 'app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component'; -import { SshUserSettingsFingerprintsService } from 'app/shared/user-settings/ssh-settings/ssh-user-settings.service'; +import { SshUserSettingsFingerprintsService } from 'app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.service'; describe('SshUserSettingsFingerprintsComponent', () => { let fixture: ComponentFixture; From 5115383e3e0f80eacad25fdf004a682ba6a51070 Mon Sep 17 00:00:00 2001 From: entholzer Date: Fri, 6 Dec 2024 11:47:02 +0100 Subject: [PATCH 6/7] added displaying EC fingerprint --- .../ssh-user-settings-fingerprints.component.html | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.html b/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.html index b19433bc9069..ef9949c49798 100644 --- a/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.html +++ b/src/main/webapp/app/shared/user-settings/ssh-settings/fingerprints/ssh-user-settings-fingerprints.component.html @@ -44,6 +44,17 @@

} + @if (sshFingerprints && sshFingerprints['EC']) { +
+
+ {{ 'ECDSA' }} +
+
+ {{ sshFingerprints['EC'] }} +
+
+ } +
From d35c826deabc75c7d6fa1789f046ee04ef189b19 Mon Sep 17 00:00:00 2001 From: entholzer Date: Fri, 6 Dec 2024 12:14:05 +0100 Subject: [PATCH 7/7] fix architecture test --- .../programming/icl/SshFingerprintsProviderIntegrationTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderIntegrationTest.java index f81b94d5f386..4791e0273be1 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderIntegrationTest.java @@ -23,7 +23,7 @@ import de.tum.cit.aet.artemis.programming.service.localvc.ssh.HashUtils; import de.tum.cit.aet.artemis.shared.base.AbstractSpringIntegrationLocalCILocalVCTest; -public class SshFingerprintsProviderIntegrationTest extends AbstractSpringIntegrationLocalCILocalVCTest { +class SshFingerprintsProviderIntegrationTest extends AbstractSpringIntegrationLocalCILocalVCTest { private static final String TEST_PREFIX = "sshFingerprintsTest";