diff --git a/web/packages/teleterm/src/agentCleanupDaemon/agentCleanupDaemon.js b/web/packages/teleterm/src/agentCleanupDaemon/agentCleanupDaemon.js index 24fb31476d156..8d2185e51de3c 100644 --- a/web/packages/teleterm/src/agentCleanupDaemon/agentCleanupDaemon.js +++ b/web/packages/teleterm/src/agentCleanupDaemon/agentCleanupDaemon.js @@ -83,7 +83,7 @@ const logger = createLogger({ maxsize: 4194304, // 4 MB - max size of a single file maxFiles: 5, dirname: logsDir, - filename: 'cleanup.log', + filename: 'agent-cleanup.log', }), ], }).child({ diff --git a/web/packages/teleterm/src/mainProcess/agentDownloader/fileDownloader.test.ts b/web/packages/teleterm/src/mainProcess/agentDownloader/fileDownloader.test.ts index 3bc814613874c..04a4d5ff7abf0 100644 --- a/web/packages/teleterm/src/mainProcess/agentDownloader/fileDownloader.test.ts +++ b/web/packages/teleterm/src/mainProcess/agentDownloader/fileDownloader.test.ts @@ -120,7 +120,7 @@ test('rejects a promise when an unexpected error occurs', async () => { const result = downloader.run(URL, DOWNLOAD_DIR); expect(browserWindow.webContents.downloadURL).toHaveBeenCalledWith(URL); - await expect(result).rejects.toThrow(`Download failed.`); + await expect(result).rejects.toThrow(`Failed to download ${URL}`); expect(browserWindow.setProgressBar).toHaveBeenCalledWith(-1, { mode: 'error', }); diff --git a/web/packages/teleterm/src/mainProcess/agentDownloader/fileDownloader.ts b/web/packages/teleterm/src/mainProcess/agentDownloader/fileDownloader.ts index f6167f8904512..903807a728734 100644 --- a/web/packages/teleterm/src/mainProcess/agentDownloader/fileDownloader.ts +++ b/web/packages/teleterm/src/mainProcess/agentDownloader/fileDownloader.ts @@ -99,11 +99,7 @@ export class FileDownloader implements IFileDownloader { // TODO(gzdunek): electron doesn't expose much information about why the download failed. // Fortunately, there is a PR in works that will add more info https://github.com/electron/electron/pull/38859. // Use DownloadItem.getLastReason() when it gets merged. - onDownloadError( - new Error( - `Download failed. Requested file may not exist or is temporarily unavailable.` - ) - ); + onDownloadError(new Error(`Failed to download ${item.getURL()}`)); break; case 'cancelled': onDownloadError(new Error('Download was cancelled.')); diff --git a/web/packages/teleterm/src/mainProcess/agentRunner/agentRunner.test.ts b/web/packages/teleterm/src/mainProcess/agentRunner/agentRunner.test.ts index d16460cf3f1ac..8e68bf960df6d 100644 --- a/web/packages/teleterm/src/mainProcess/agentRunner/agentRunner.test.ts +++ b/web/packages/teleterm/src/mainProcess/agentRunner/agentRunner.test.ts @@ -88,6 +88,7 @@ test('agent process and cleanup daemon start with correct arguments', async () = agentBinaryPath, 'start', `--config=${userDataDir}/agents/cluster.local/config.yaml`, + '--insecure', ]); expect(cleanupDaemon.spawnargs).toEqual([ process.argv[0], // path to Node.js bin diff --git a/web/packages/teleterm/src/mainProcess/agentRunner/agentRunner.ts b/web/packages/teleterm/src/mainProcess/agentRunner/agentRunner.ts index ce24149000e85..797985cccc676 100644 --- a/web/packages/teleterm/src/mainProcess/agentRunner/agentRunner.ts +++ b/web/packages/teleterm/src/mainProcess/agentRunner/agentRunner.ts @@ -71,6 +71,7 @@ export class AgentRunner { 'start', `--config=${configFile}`, this.settings.isLocalBuild && '--skip-version-check', + this.settings.tshd.insecure && '--insecure', ].filter(Boolean); this.logger.info( diff --git a/web/packages/teleterm/src/ui/ConnectMyComputer/DocumentConnectMyComputerSetup/DocumentConnectMyComputerSetup.tsx b/web/packages/teleterm/src/ui/ConnectMyComputer/DocumentConnectMyComputerSetup/DocumentConnectMyComputerSetup.tsx index 56cb32cd802c1..c2a90c4261bac 100644 --- a/web/packages/teleterm/src/ui/ConnectMyComputer/DocumentConnectMyComputerSetup/DocumentConnectMyComputerSetup.tsx +++ b/web/packages/teleterm/src/ui/ConnectMyComputer/DocumentConnectMyComputerSetup/DocumentConnectMyComputerSetup.tsx @@ -89,6 +89,13 @@ function Information(props: { onSetUpAgentClick(): void }) { access your computer as {systemUsername}.

+ Note that users with administrator privileges can assign that role to + themselves or craft another role which grants access to the node. We + recommend using Connect My Computer only in scenarios where no other + user could plausibly gain access to the node, such as when exploring a + Teleport cluster as its only user or in a home lab. +
+
Your computer will be shared while Teleport Connect is open. To stop sharing, close Teleport Connect or stop the agent through the Connect My Computer tab. Sharing will resume on app restart, unless you stop the diff --git a/web/packages/teleterm/src/ui/ConnectMyComputer/DocumentConnectMyComputerStatus/DocumentConnectMyComputerStatus.tsx b/web/packages/teleterm/src/ui/ConnectMyComputer/DocumentConnectMyComputerStatus/DocumentConnectMyComputerStatus.tsx index 6db9b823d3dbc..b4dd36700292a 100644 --- a/web/packages/teleterm/src/ui/ConnectMyComputer/DocumentConnectMyComputerStatus/DocumentConnectMyComputerStatus.tsx +++ b/web/packages/teleterm/src/ui/ConnectMyComputer/DocumentConnectMyComputerStatus/DocumentConnectMyComputerStatus.tsx @@ -31,7 +31,7 @@ import { Transition } from 'react-transition-group'; import { makeLabelTag } from 'teleport/components/formatters'; import { MenuIcon } from 'shared/components/MenuAction'; -import { CircleCheck, Laptop, Moon, Warning } from 'design/Icon'; +import * as icons from 'design/Icon'; import Indicator from 'design/Indicator'; import { @@ -192,11 +192,12 @@ export function DocumentConnectMyComputerStatus( display: flex; `} > - + {/** The node name can be changed, so it might be different from the system hostname. */} {agentNode?.hostname || hostname} props.theme.space[1]}px; @@ -284,14 +285,16 @@ export function DocumentConnectMyComputerStatus( <> {isRunning ? ( - Any cluster user with the role {roleName} can - now access your computer as {systemUsername}. + Cluster users with the role {roleName} and + users with administrator privileges can now access your + computer as {systemUsername}. ) : ( - Connecting your computer will allow any cluster user with the - role {roleName} to access it as an SSH - resource with the user {systemUsername}. + Starting the agent will allow clusters users with the role{' '} + {roleName} and users with administrator + privileges to access it as an SSH resource as the user{' '} + {systemUsername}. )} {showConnectAndStopAgentButtons ? ( @@ -431,13 +434,13 @@ function prettifyCurrentAction(currentAction: CurrentAction): { switch (currentAction.agentProcessState.status) { case 'not-started': { return { - Icon: Moon, + Icon: icons.Moon, title: 'Agent not running', }; } case 'running': { return { - Icon: props => , + Icon: props => , title: 'Agent running', }; } @@ -447,7 +450,7 @@ function prettifyCurrentAction(currentAction: CurrentAction): { if (exitedSuccessfully) { return { - Icon: Moon, + Icon: icons.Moon, title: 'Agent not running', }; } else { @@ -515,7 +518,7 @@ function prettifyCurrentAction(currentAction: CurrentAction): { } case 'success': { return { - Icon: CircleCheck, + Icon: icons.CircleCheck, title: 'Agent removed', error: currentAction.attempt.statusText, }; @@ -528,7 +531,7 @@ function prettifyCurrentAction(currentAction: CurrentAction): { } } -const StyledWarning = styled(Warning).attrs({ +const StyledWarning = styled(icons.Warning).attrs({ color: 'error.main', })``; diff --git a/web/packages/teleterm/src/ui/ConnectMyComputer/connectMyComputerContext.tsx b/web/packages/teleterm/src/ui/ConnectMyComputer/connectMyComputerContext.tsx index 40b0164059f5e..12e95d7842aa5 100644 --- a/web/packages/teleterm/src/ui/ConnectMyComputer/connectMyComputerContext.tsx +++ b/web/packages/teleterm/src/ui/ConnectMyComputer/connectMyComputerContext.tsx @@ -232,7 +232,9 @@ export const ConnectMyComputerContextProvider: FC<{ const [killAgentAttempt, killAgent] = useAsync( useCallback(async () => { setCurrentActionKind('kill'); + await connectMyComputerService.killAgent(rootClusterUri); + setCurrentActionKind('observe-process'); workspacesService.setConnectMyComputerAutoStart(rootClusterUri, false); }, [connectMyComputerService, rootClusterUri, workspacesService]) @@ -241,6 +243,7 @@ export const ConnectMyComputerContextProvider: FC<{ const markAgentAsConfigured = useCallback(() => { setAgentConfiguredAttempt(makeSuccessAttempt(true)); }, [setAgentConfiguredAttempt]); + const markAgentAsNotConfigured = useCallback(() => { setDownloadAgentAttempt(makeEmptyAttempt()); setAgentConfiguredAttempt(makeSuccessAttempt(false)); @@ -267,10 +270,12 @@ export const ConnectMyComputerContextProvider: FC<{ const [removeAgentAttempt, removeAgent] = useAsync( useCallback(async () => { + // killAgent sets the current action to 'kill'. const [, error] = await killAgent(); if (error) { throw error; } + setCurrentActionKind('remove'); let hasAccessDeniedError = false; @@ -299,6 +304,18 @@ export const ConnectMyComputerContextProvider: FC<{ // We have to remove connections before removing the agent directory, because // we get the node UUID from the that directory. + // + // Theoretically, removing connections only at this stage means that if there are active + // connections from the app at the time of killing the agent above, the shutdown of the agent + // will take a couple of extra seconds while the agent waits for the connections to close. + // However, we'd have to remove the connections before calling `killAgent` above and this + // messes up error handling somewhat. `removeConnections` would have to be executed after the + // current action is set to 'kill' so that any errors thrown by `removeConnections` are + // correctly reported in the UI. + // + // Otherwise, if `removeConnections` was called before `killAgent` and the function threw an + // error, it'd simply be swallowed. It'd be shown once the current action is set to 'remove', + // but this would never happen because of the error. await removeConnections(); ctx.workspacesService.removeConnectMyComputerState(rootClusterUri); await ctx.connectMyComputerService.removeAgentDirectory(rootClusterUri);