From fcd2c0b2ae1f33774df8b04cdf4ae140627c314c Mon Sep 17 00:00:00 2001 From: entholzer Date: Wed, 4 Dec 2024 22:09:29 +0100 Subject: [PATCH 01/22] 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 98aee32d661aefb42110b96c7bfc0dcd33aceb97 Mon Sep 17 00:00:00 2001 From: entholzer Date: Thu, 5 Dec 2024 07:42:49 +0100 Subject: [PATCH 02/22] 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 ede4677504618d0e8e2322ea4692983141c1d17c Mon Sep 17 00:00:00 2001 From: entholzer Date: Thu, 5 Dec 2024 08:00:21 +0100 Subject: [PATCH 03/22] 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 832f1560b48a0f35714961852208d21ba5d7e448 Mon Sep 17 00:00:00 2001 From: entholzer Date: Thu, 5 Dec 2024 08:03:02 +0100 Subject: [PATCH 04/22] 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 1d501d78837fa8bd3459446d0a5a770c1dd34637 Mon Sep 17 00:00:00 2001 From: entholzer Date: Thu, 5 Dec 2024 08:06:46 +0100 Subject: [PATCH 05/22] 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 bd6103e60c8c3b398d09b97b50b77b4bdb5bda1c Mon Sep 17 00:00:00 2001 From: entholzer Date: Fri, 6 Dec 2024 11:47:02 +0100 Subject: [PATCH 06/22] 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 e56878ba1aa4c6e299f748a42c8242e243249a85 Mon Sep 17 00:00:00 2001 From: entholzer Date: Fri, 6 Dec 2024 12:14:05 +0100 Subject: [PATCH 07/22] 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"; From b2f251ea80ecbe5b5503509442d29404003269b9 Mon Sep 17 00:00:00 2001 From: entholzer Date: Fri, 6 Dec 2024 12:55:34 +0100 Subject: [PATCH 08/22] remove test --- ...shFingerprintsProviderIntegrationTest.java | 121 ++++++++---------- 1 file changed, 50 insertions(+), 71 deletions(-) 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 4791e0273be1..23ab654dab31 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 @@ -1,77 +1,56 @@ 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; 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.getSha256Fingerprint(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); - } - } + // + // 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.getSha256Fingerprint(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); + // } + // } } From d14bdac01c384217c09e0269fc1fcd138f575980 Mon Sep 17 00:00:00 2001 From: entholzer Date: Fri, 6 Dec 2024 13:57:26 +0100 Subject: [PATCH 09/22] re add test? --- ...shFingerprintsProviderIntegrationTest.java | 128 +++++++++++------- 1 file changed, 78 insertions(+), 50 deletions(-) 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 23ab654dab31..d2f0cc439b6c 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 @@ -1,56 +1,84 @@ 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.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; + +import de.tum.cit.aet.artemis.programming.service.localvc.ssh.HashUtils; +import de.tum.cit.aet.artemis.programming.service.localvc.ssh.SshFingerprintsProviderService; import de.tum.cit.aet.artemis.shared.base.AbstractSpringIntegrationLocalCILocalVCTest; 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.getSha256Fingerprint(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); - // } - // } + + private static final String TEST_PREFIX = "sshFingerprintsTest"; + + @MockitoSpyBean + private SshServer sshServer; + + @Mock + private KeyPairProvider keyPairProvider; + + private String expectedFingerprint; + + @Autowired + private SshFingerprintsProviderService sshFingerprintsProviderService; + + @BeforeEach + void setup() throws Exception { + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); + keyPairGenerator.initialize(2048); + KeyPair testKeyPair = keyPairGenerator.generateKeyPair(); + + expectedFingerprint = HashUtils.getSha256Fingerprint(testKeyPair.getPublic()); + doReturn(keyPairProvider).when(sshServer).getKeyPairProvider(); + doReturn(Collections.singleton(testKeyPair)).when(keyPairProvider).loadKeys(null); + + sshFingerprintsProviderService = new SshFingerprintsProviderService(sshServer); + } + + @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); + } + } } From dcde0c897bab638348e390679900626985c4d274 Mon Sep 17 00:00:00 2001 From: entholzer Date: Fri, 6 Dec 2024 15:36:23 +0100 Subject: [PATCH 10/22] adapt tests --- ...shFingerprintsProviderIntegrationTest.java | 46 +++-------- .../SshFingerprintsProviderServiceTest.java | 79 +++++++++++++++++++ 2 files changed, 88 insertions(+), 37 deletions(-) create mode 100644 src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderServiceTest.java 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 d2f0cc439b6c..f0b3aa2a5b02 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 @@ -2,21 +2,15 @@ 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.HashMap; 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.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; @@ -30,16 +24,10 @@ class SshFingerprintsProviderIntegrationTest extends AbstractSpringIntegrationLo private static final String TEST_PREFIX = "sshFingerprintsTest"; @MockitoSpyBean - private SshServer sshServer; - - @Mock - private KeyPairProvider keyPairProvider; + private SshFingerprintsProviderService fingerprintsProviderService; private String expectedFingerprint; - @Autowired - private SshFingerprintsProviderService sshFingerprintsProviderService; - @BeforeEach void setup() throws Exception { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); @@ -47,38 +35,22 @@ void setup() throws Exception { KeyPair testKeyPair = keyPairGenerator.generateKeyPair(); expectedFingerprint = HashUtils.getSha256Fingerprint(testKeyPair.getPublic()); - doReturn(keyPairProvider).when(sshServer).getKeyPairProvider(); - doReturn(Collections.singleton(testKeyPair)).when(keyPairProvider).loadKeys(null); - - sshFingerprintsProviderService = new SshFingerprintsProviderService(sshServer); } @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); - } + class SshFingerprintsProviderShould { @Test @WithMockUser(username = TEST_PREFIX + "student1", roles = "USER") - void shouldReturnNoFingerprintsWithoutKeyProviderSetup() throws Exception { - doReturn(null).when(sshServer).getKeyPairProvider(); + void returnFingerprints() throws Exception { + Map expectedFingerprints = new HashMap<>(); + expectedFingerprints.put("RSA", expectedFingerprint); + doReturn(expectedFingerprints).when(fingerprintsProviderService).getSshFingerPrints(); 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); + assertThat(response.get("RSA")).isNotNull(); + assertThat(response.get("RSA")).isEqualTo(expectedFingerprint); } } } diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderServiceTest.java new file mode 100644 index 000000000000..777a549f5561 --- /dev/null +++ b/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderServiceTest.java @@ -0,0 +1,79 @@ +package de.tum.cit.aet.artemis.programming.icl; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.doReturn; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.util.Collections; +import java.util.HashMap; +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 de.tum.cit.aet.artemis.programming.service.localvc.ssh.HashUtils; +import de.tum.cit.aet.artemis.programming.service.localvc.ssh.SshFingerprintsProviderService; +import de.tum.cit.aet.artemis.shared.base.AbstractSpringIntegrationLocalCILocalVCTest; + +class SshFingerprintsProviderServiceTest extends AbstractSpringIntegrationLocalCILocalVCTest { + + private static final String TEST_PREFIX = "sshFingerprintsTest"; + + @Mock + private SshServer sshServer; + + @Mock + private KeyPairProvider keyPairProvider; + + private SshFingerprintsProviderService fingerprintsProviderService; + + private String expectedFingerprint; + + @Nested + class SshFingerprintsProviderServiceShould { + + Map expectedFingerprints; + + KeyPair testKeyPair; + + @BeforeEach + void setup() throws Exception { + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); + keyPairGenerator.initialize(2048); + testKeyPair = keyPairGenerator.generateKeyPair(); + + expectedFingerprints = new HashMap<>(); + expectedFingerprint = HashUtils.getSha256Fingerprint(testKeyPair.getPublic()); + } + + @Test + void returnFingerprints() throws GeneralSecurityException, IOException { + expectedFingerprints.put("RSA", expectedFingerprint); + doReturn(Collections.singleton(testKeyPair)).when(keyPairProvider).loadKeys(null); + doReturn(keyPairProvider).when(sshServer).getKeyPairProvider(); + fingerprintsProviderService = new SshFingerprintsProviderService(sshServer); + + var actualFingerprints = fingerprintsProviderService.getSshFingerPrints(); + + assertThat(actualFingerprints).isEqualTo(expectedFingerprints); + } + + @Test + void notReturnFingerprintsWhenKeysProviderIsNull() throws GeneralSecurityException, IOException { + doReturn(Collections.singleton(testKeyPair)).when(keyPairProvider).loadKeys(null); + doReturn(null).when(sshServer).getKeyPairProvider(); + fingerprintsProviderService = new SshFingerprintsProviderService(sshServer); + + var actualFingerprints = fingerprintsProviderService.getSshFingerPrints(); + + assertThat(actualFingerprints).isEqualTo(expectedFingerprints); + } + } +} From 2ec7f16853a89c98bbd13c27fa860346976d57ef Mon Sep 17 00:00:00 2001 From: entholzer Date: Fri, 6 Dec 2024 15:50:22 +0100 Subject: [PATCH 11/22] comment out resource test --- ...shFingerprintsProviderIntegrationTest.java | 86 ++++++++----------- 1 file changed, 37 insertions(+), 49 deletions(-) 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 f0b3aa2a5b02..5383b9eaa4c7 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 @@ -1,56 +1,44 @@ package de.tum.cit.aet.artemis.programming.icl; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.doReturn; - -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.util.HashMap; -import java.util.Map; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.springframework.http.HttpStatus; -import org.springframework.security.test.context.support.WithMockUser; -import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; - -import de.tum.cit.aet.artemis.programming.service.localvc.ssh.HashUtils; -import de.tum.cit.aet.artemis.programming.service.localvc.ssh.SshFingerprintsProviderService; import de.tum.cit.aet.artemis.shared.base.AbstractSpringIntegrationLocalCILocalVCTest; class SshFingerprintsProviderIntegrationTest extends AbstractSpringIntegrationLocalCILocalVCTest { - private static final String TEST_PREFIX = "sshFingerprintsTest"; - - @MockitoSpyBean - private SshFingerprintsProviderService fingerprintsProviderService; - - private String expectedFingerprint; - - @BeforeEach - void setup() throws Exception { - KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); - keyPairGenerator.initialize(2048); - KeyPair testKeyPair = keyPairGenerator.generateKeyPair(); - - expectedFingerprint = HashUtils.getSha256Fingerprint(testKeyPair.getPublic()); - } - - @Nested - class SshFingerprintsProviderShould { - - @Test - @WithMockUser(username = TEST_PREFIX + "student1", roles = "USER") - void returnFingerprints() throws Exception { - Map expectedFingerprints = new HashMap<>(); - expectedFingerprints.put("RSA", expectedFingerprint); - doReturn(expectedFingerprints).when(fingerprintsProviderService).getSshFingerPrints(); - - var response = request.get("/api/ssh-fingerprints", HttpStatus.OK, Map.class); - - assertThat(response.get("RSA")).isNotNull(); - assertThat(response.get("RSA")).isEqualTo(expectedFingerprint); - } - } + // private static final String TEST_PREFIX = "sshFingerprintsTest"; + // + // @Mock + // private SshFingerprintsProviderService fingerprintsProviderService; + // + // @Autowired + // private SshFingerprintsProviderResource sshFingerprintsProviderResource; + // + // private String expectedFingerprint; + // + // @BeforeEach + // void setup() throws Exception { + // KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); + // keyPairGenerator.initialize(2048); + // KeyPair testKeyPair = keyPairGenerator.generateKeyPair(); + // + // expectedFingerprint = HashUtils.getSha256Fingerprint(testKeyPair.getPublic()); + // } + // + // @Nested + // class SshFingerprintsProviderShould { + // + // @Test + // @WithMockUser(username = TEST_PREFIX + "student1", roles = "USER") + // void returnFingerprints() throws Exception { + // sshFingerprintsProviderResource = new SshFingerprintsProviderResource(fingerprintsProviderService); + // + // Map expectedFingerprints = new HashMap<>(); + // expectedFingerprints.put("RSA", expectedFingerprint); + // doReturn(expectedFingerprints).when(fingerprintsProviderService).getSshFingerPrints(); + // + // var response = request.get("/api/ssh-fingerprints", HttpStatus.OK, Map.class); + // + // assertThat(response.get("RSA")).isNotNull(); + // assertThat(response.get("RSA")).isEqualTo(expectedFingerprint); + // } + // } } From f12661befc78d63101c4e5bcb54f4c9a2b392546 Mon Sep 17 00:00:00 2001 From: entholzer Date: Fri, 6 Dec 2024 16:11:10 +0100 Subject: [PATCH 12/22] use different yml parameter --- .../programming/service/localvc/ssh/SshConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/SshConfiguration.java b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/SshConfiguration.java index 190b1732efe1..1027690efb63 100644 --- a/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/SshConfiguration.java +++ b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/SshConfiguration.java @@ -31,7 +31,7 @@ public class SshConfiguration { @Value("${artemis.version-control.ssh-port:7921}") private int sshPort; - @Value("${artemis.version-control.ssh-host-key-path:null}") + @Value("${artemis.version-control.ssh-key-path:null}") private Optional sshHostKeyPath; @Value("${server.url}") From 2c733c0b55050919d4685063f6c037005b70bc27 Mon Sep 17 00:00:00 2001 From: entholzer Date: Fri, 6 Dec 2024 16:29:45 +0100 Subject: [PATCH 13/22] undo config change --- .../programming/service/localvc/ssh/SshConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/SshConfiguration.java b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/SshConfiguration.java index 1027690efb63..190b1732efe1 100644 --- a/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/SshConfiguration.java +++ b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/SshConfiguration.java @@ -31,7 +31,7 @@ public class SshConfiguration { @Value("${artemis.version-control.ssh-port:7921}") private int sshPort; - @Value("${artemis.version-control.ssh-key-path:null}") + @Value("${artemis.version-control.ssh-host-key-path:null}") private Optional sshHostKeyPath; @Value("${server.url}") From 2a7d7f592a32cad9b82efcee0c3e6c1d1d2324f4 Mon Sep 17 00:00:00 2001 From: entholzer Date: Fri, 6 Dec 2024 17:03:07 +0100 Subject: [PATCH 14/22] fix tests --- ...shFingerprintsProviderIntegrationTest.java | 44 ----------------- .../SshFingerprintsProviderServiceTest.java | 20 ++++++++ .../icl/SshFingerprintsProviderTest.java | 47 +++++++++++++++++++ 3 files changed, 67 insertions(+), 44 deletions(-) delete mode 100644 src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderIntegrationTest.java create mode 100644 src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderTest.java 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 deleted file mode 100644 index 5383b9eaa4c7..000000000000 --- a/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderIntegrationTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package de.tum.cit.aet.artemis.programming.icl; - -import de.tum.cit.aet.artemis.shared.base.AbstractSpringIntegrationLocalCILocalVCTest; - -class SshFingerprintsProviderIntegrationTest extends AbstractSpringIntegrationLocalCILocalVCTest { - - // private static final String TEST_PREFIX = "sshFingerprintsTest"; - // - // @Mock - // private SshFingerprintsProviderService fingerprintsProviderService; - // - // @Autowired - // private SshFingerprintsProviderResource sshFingerprintsProviderResource; - // - // private String expectedFingerprint; - // - // @BeforeEach - // void setup() throws Exception { - // KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); - // keyPairGenerator.initialize(2048); - // KeyPair testKeyPair = keyPairGenerator.generateKeyPair(); - // - // expectedFingerprint = HashUtils.getSha256Fingerprint(testKeyPair.getPublic()); - // } - // - // @Nested - // class SshFingerprintsProviderShould { - // - // @Test - // @WithMockUser(username = TEST_PREFIX + "student1", roles = "USER") - // void returnFingerprints() throws Exception { - // sshFingerprintsProviderResource = new SshFingerprintsProviderResource(fingerprintsProviderService); - // - // Map expectedFingerprints = new HashMap<>(); - // expectedFingerprints.put("RSA", expectedFingerprint); - // doReturn(expectedFingerprints).when(fingerprintsProviderService).getSshFingerPrints(); - // - // var response = request.get("/api/ssh-fingerprints", HttpStatus.OK, Map.class); - // - // assertThat(response.get("RSA")).isNotNull(); - // assertThat(response.get("RSA")).isEqualTo(expectedFingerprint); - // } - // } -} diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderServiceTest.java index 777a549f5561..06f8a9add964 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderServiceTest.java @@ -1,7 +1,9 @@ package de.tum.cit.aet.artemis.programming.icl; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; import java.io.IOException; import java.security.GeneralSecurityException; @@ -11,6 +13,8 @@ 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.junit.jupiter.api.BeforeEach; @@ -75,5 +79,21 @@ void notReturnFingerprintsWhenKeysProviderIsNull() throws GeneralSecurityExcepti assertThat(actualFingerprints).isEqualTo(expectedFingerprints); } + + @Test + void shouldThrowBadRequestExceptionWhenLoadKeysThrowsIOException() throws GeneralSecurityException, IOException { + doReturn(Collections.singleton(testKeyPair)).when(keyPairProvider).loadKeys(null); + doThrow(new IOException()).when(keyPairProvider).loadKeys(null); + doReturn(keyPairProvider).when(sshServer).getKeyPairProvider(); + fingerprintsProviderService = new SshFingerprintsProviderService(sshServer); + try { + fingerprintsProviderService.getSshFingerPrints(); + } + catch (BadRequestException e) { + return; + } + fail("Should have thrown an exception"); + + } } } diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderTest.java new file mode 100644 index 000000000000..7afd5a9e48fc --- /dev/null +++ b/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderTest.java @@ -0,0 +1,47 @@ +package de.tum.cit.aet.artemis.programming.icl; + +import static de.tum.cit.aet.artemis.core.config.Constants.PROFILE_LOCALVC; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.doReturn; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.springframework.context.annotation.Profile; +import org.springframework.security.test.context.support.WithMockUser; + +import de.tum.cit.aet.artemis.programming.service.localvc.ssh.SshFingerprintsProviderService; +import de.tum.cit.aet.artemis.programming.web.localvc.ssh.SshFingerprintsProviderResource; +import de.tum.cit.aet.artemis.shared.base.AbstractSpringIntegrationLocalCILocalVCTest; + +@Profile(PROFILE_LOCALVC) +class SshFingerprintsProviderTest extends AbstractSpringIntegrationLocalCILocalVCTest { + + private static final String TEST_PREFIX = "sshFingerprintsTest"; + + @Mock + SshFingerprintsProviderService sshFingerprintsProviderService; + + SshFingerprintsProviderResource sshFingerprintsProviderResource; + + @BeforeEach + void setUp() { + sshFingerprintsProviderResource = new SshFingerprintsProviderResource(sshFingerprintsProviderService); + } + + @Test + @WithMockUser(username = TEST_PREFIX + "student1", roles = "USER") + void shouldReturnFingerprints() throws Exception { + Map expectedFingerprints = new HashMap<>(); + expectedFingerprints.put("RSA", "key"); + doReturn(expectedFingerprints).when(sshFingerprintsProviderService).getSshFingerPrints(); + + var response = sshFingerprintsProviderResource.getSshFingerprints().getBody(); + + assertThat(response).isNotNull(); + assertThat(response.get("RSA")).isEqualTo("key"); + } +} From 2cdbdf9a9058b41d3be12491661ddf32b3ef9cf1 Mon Sep 17 00:00:00 2001 From: entholzer Date: Fri, 6 Dec 2024 21:26:52 +0100 Subject: [PATCH 15/22] fix test and improve translation --- src/main/webapp/i18n/de/userSettings.json | 2 +- src/main/webapp/i18n/en/userSettings.json | 2 +- .../icl/SshFingerprintsProviderTest.java | 27 +++---------------- 3 files changed, 5 insertions(+), 26 deletions(-) diff --git a/src/main/webapp/i18n/de/userSettings.json b/src/main/webapp/i18n/de/userSettings.json index 84953e9f1707..3a3b4cb33a22 100644 --- a/src/main/webapp/i18n/de/userSettings.json +++ b/src/main/webapp/i18n/de/userSettings.json @@ -55,7 +55,7 @@ "expiresOn": "Läuft ab am", "hasExpiredOn": "Abgelaufen am", "fingerprint": "Fingerabdruck", - "fingerprints": "Fingerabdrücke", + "fingerprints": "SSH Fingerabdrücke anzeigen", "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", diff --git a/src/main/webapp/i18n/en/userSettings.json b/src/main/webapp/i18n/en/userSettings.json index 5bf3c30161da..a2f4e0a90f57 100644 --- a/src/main/webapp/i18n/en/userSettings.json +++ b/src/main/webapp/i18n/en/userSettings.json @@ -55,7 +55,7 @@ "expiresOn": "Expires on", "hasExpiredOn": "Expired on", "fingerprint": "Fingerprint", - "fingerprints": "Fingerprints", + "fingerprints": "Show SSH 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", diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderTest.java index 7afd5a9e48fc..c5c85067b8e3 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderTest.java @@ -2,19 +2,14 @@ import static de.tum.cit.aet.artemis.core.config.Constants.PROFILE_LOCALVC; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.doReturn; -import java.util.HashMap; import java.util.Map; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.Mock; import org.springframework.context.annotation.Profile; +import org.springframework.http.HttpStatus; import org.springframework.security.test.context.support.WithMockUser; -import de.tum.cit.aet.artemis.programming.service.localvc.ssh.SshFingerprintsProviderService; -import de.tum.cit.aet.artemis.programming.web.localvc.ssh.SshFingerprintsProviderResource; import de.tum.cit.aet.artemis.shared.base.AbstractSpringIntegrationLocalCILocalVCTest; @Profile(PROFILE_LOCALVC) @@ -22,26 +17,10 @@ class SshFingerprintsProviderTest extends AbstractSpringIntegrationLocalCILocalV private static final String TEST_PREFIX = "sshFingerprintsTest"; - @Mock - SshFingerprintsProviderService sshFingerprintsProviderService; - - SshFingerprintsProviderResource sshFingerprintsProviderResource; - - @BeforeEach - void setUp() { - sshFingerprintsProviderResource = new SshFingerprintsProviderResource(sshFingerprintsProviderService); - } - @Test @WithMockUser(username = TEST_PREFIX + "student1", roles = "USER") void shouldReturnFingerprints() throws Exception { - Map expectedFingerprints = new HashMap<>(); - expectedFingerprints.put("RSA", "key"); - doReturn(expectedFingerprints).when(sshFingerprintsProviderService).getSshFingerPrints(); - - var response = sshFingerprintsProviderResource.getSshFingerprints().getBody(); - - assertThat(response).isNotNull(); - assertThat(response.get("RSA")).isEqualTo("key"); + var response = request.get("/api/ssh-fingerprints", HttpStatus.OK, Map.class); + assertThat(response.get("EC")).isNotNull(); } } From 5cfb6c64cebb6224e10d4483c9f0d6fbb706c515 Mon Sep 17 00:00:00 2001 From: entholzer Date: Fri, 6 Dec 2024 21:31:18 +0100 Subject: [PATCH 16/22] use assertj fail instead of junit fail to fix architecture test --- .../programming/icl/SshFingerprintsProviderServiceTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderServiceTest.java index 06f8a9add964..d76b30da7c92 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderServiceTest.java @@ -1,7 +1,7 @@ package de.tum.cit.aet.artemis.programming.icl; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.fail; +import static org.assertj.core.api.Assertions.fail; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; @@ -93,7 +93,6 @@ void shouldThrowBadRequestExceptionWhenLoadKeysThrowsIOException() throws Genera return; } fail("Should have thrown an exception"); - } } } From c25eeae8bc718c59c6db1f70c35650ef3b177d8a Mon Sep 17 00:00:00 2001 From: entholzer Date: Fri, 6 Dec 2024 21:31:46 +0100 Subject: [PATCH 17/22] remove unused code --- .../programming/icl/SshFingerprintsProviderServiceTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderServiceTest.java index d76b30da7c92..36bd8f4cd540 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderServiceTest.java @@ -28,8 +28,6 @@ class SshFingerprintsProviderServiceTest extends AbstractSpringIntegrationLocalCILocalVCTest { - private static final String TEST_PREFIX = "sshFingerprintsTest"; - @Mock private SshServer sshServer; From 4645b92f9a6d7ed028865cfb264ea1007971c3a2 Mon Sep 17 00:00:00 2001 From: entholzer Date: Fri, 6 Dec 2024 21:45:51 +0100 Subject: [PATCH 18/22] add code rabbit suggestion --- .../programming/icl/SshFingerprintsProviderServiceTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderServiceTest.java index 36bd8f4cd540..8c3381b73a38 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/icl/SshFingerprintsProviderServiceTest.java @@ -69,7 +69,6 @@ void returnFingerprints() throws GeneralSecurityException, IOException { @Test void notReturnFingerprintsWhenKeysProviderIsNull() throws GeneralSecurityException, IOException { - doReturn(Collections.singleton(testKeyPair)).when(keyPairProvider).loadKeys(null); doReturn(null).when(sshServer).getKeyPairProvider(); fingerprintsProviderService = new SshFingerprintsProviderService(sshServer); From f26aa5332e7a4c6db06ad262f6dfc0033426c74b Mon Sep 17 00:00:00 2001 From: entholzer Date: Sat, 7 Dec 2024 20:53:57 +0100 Subject: [PATCH 19/22] fix style --- .../localvc/ssh/SshFingerprintsProviderService.java | 7 +++++++ 1 file changed, 7 insertions(+) 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 ff2e7c99e324..77c386aa95b6 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 @@ -31,6 +31,13 @@ public SshFingerprintsProviderService(SshServer sshServer) { this.sshServer = sshServer; } + /** + * Retrieves the SSH key fingerprints from the stored SSH keys + * + * @return a map containing the SSH key fingerprints, where the key is the algorithm + * of the public key and the value is its SHA-256 fingerprint. + * @throws BadRequestException if there is an error loading keys from the SSH server. + */ public Map getSshFingerPrints() { Map fingerprints = new HashMap<>(); KeyPairProvider keyPairProvider = sshServer.getKeyPairProvider(); From 3abbcd2a52fbd374542c97a9ab38edd90b357075 Mon Sep 17 00:00:00 2001 From: Simon Entholzer <33342534+SimonEntholzer@users.noreply.github.com> Date: Tue, 10 Dec 2024 16:37:04 +0100 Subject: [PATCH 20/22] Update src/main/webapp/i18n/de/userSettings.json Co-authored-by: Yannik Schmidt --- src/main/webapp/i18n/de/userSettings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/i18n/de/userSettings.json b/src/main/webapp/i18n/de/userSettings.json index 3a3b4cb33a22..e745320fbfbc 100644 --- a/src/main/webapp/i18n/de/userSettings.json +++ b/src/main/webapp/i18n/de/userSettings.json @@ -57,7 +57,7 @@ "fingerprint": "Fingerabdruck", "fingerprints": "SSH Fingerabdrücke anzeigen", "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.", + "fingerprintsExplanation": "Mit SSH-Schlüsseln kannst du eine sichere Verbindung zwischen deinem Computer und Artemis herstellen. SSH-Fingerabdrücke stellen sicher, dass du eine Verbindung zum richtigen Gerät herstellt.", "fingerprintsLearnMore": "Lerne mehr über Fingerabdrücke", "commentUsedAsLabel": "Wenn du kein Label hinzufügst, wird der Schlüsselkommentar (sofern vorhanden) als Label verwendet.", "expiry": { From aedbd10144967bf6c0d0f54d3adcd84a940e7bb8 Mon Sep 17 00:00:00 2001 From: Simon Entholzer <33342534+SimonEntholzer@users.noreply.github.com> Date: Tue, 10 Dec 2024 16:37:16 +0100 Subject: [PATCH 21/22] Update src/main/webapp/i18n/en/userSettings.json Co-authored-by: Yannik Schmidt --- src/main/webapp/i18n/en/userSettings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/i18n/en/userSettings.json b/src/main/webapp/i18n/en/userSettings.json index a2f4e0a90f57..e81901dbbd63 100644 --- a/src/main/webapp/i18n/en/userSettings.json +++ b/src/main/webapp/i18n/en/userSettings.json @@ -57,7 +57,7 @@ "fingerprint": "Fingerprint", "fingerprints": "Show SSH 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.", + "fingerprintsExplanation": "SSH keys allow you to establish a secure connection between your computer and Artemis. SSH fingerprints verify that you connect to the correct device.", "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": { From 76d2396c070a9a9b7c36877064f78739572be600 Mon Sep 17 00:00:00 2001 From: entholzer Date: Fri, 13 Dec 2024 15:05:34 +0100 Subject: [PATCH 22/22] remove unnecessary feature toggle --- .../web/localvc/ssh/SshFingerprintsProviderResource.java | 3 --- 1 file changed, 3 deletions(-) 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 index eaaf3d345fb7..d882d82d3c3d 100644 --- 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 @@ -12,8 +12,6 @@ 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; /** @@ -37,7 +35,6 @@ public SshFingerprintsProviderResource(SshFingerprintsProviderService sshFingerp */ @GetMapping(value = "ssh-fingerprints", produces = MediaType.APPLICATION_JSON_VALUE) @EnforceAtLeastStudent - @FeatureToggle(Feature.Exports) public ResponseEntity> getSshFingerprints() { return ResponseEntity.ok().body(sshFingerprintsProviderService.getSshFingerPrints()); }