Skip to content
This repository has been archived by the owner on Feb 8, 2024. It is now read-only.

Commit

Permalink
[backport v9] Use generated token to simplify manual adding of nodes (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
mcbattirola authored Mar 3, 2022
1 parent 6d099b4 commit b2a50ab
Show file tree
Hide file tree
Showing 12 changed files with 789 additions and 102 deletions.
1 change: 0 additions & 1 deletion packages/teleport/src/Apps/AddApp/AddApp.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ const props = {
createJoinToken: () => Promise.resolve(null),
version: '5.0.0-dev',
cmd: `sudo bash -c "$(curl -fsSL 'http://localhost/scripts/86/install-app.sh?name=test&uri=http://myapp/')"`,
canCreateToken: true,
expires: '1 hour',
reset: () => null,
attempt: {
Expand Down
2 changes: 0 additions & 2 deletions packages/teleport/src/Apps/AddApp/useAddApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import useAttempt from 'shared/hooks/useAttemptNext';

export default function useAddApp(ctx: TeleportContext) {
const { attempt, run } = useAttempt('');
const canCreateToken = ctx.storeUser.getTokenAccess().create;
const user = ctx.storeUser.state.username;
const version = ctx.storeUser.state.cluster.authVersion;
const isAuthTypeLocal = !ctx.storeUser.isSso();
Expand All @@ -40,7 +39,6 @@ export default function useAddApp(ctx: TeleportContext) {

return {
user,
canCreateToken,
version,
createToken,
cmd,
Expand Down
17 changes: 14 additions & 3 deletions packages/teleport/src/Nodes/AddNode/AddNode.story.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@
*/

import React from 'react';
import { Loaded, Failed, ManuallyLocal, ManuallySSO } from './AddNode.story';
import {
Loaded,
Failed,
ManuallyWithoutTokenLocal,
ManuallyWithoutTokenSSO,
ManuallyWithToken,
} from './AddNode.story';
import { render, screen } from 'design/utils/testing';

test('render automatic tab', async () => {
Expand All @@ -29,11 +35,16 @@ test('render failed automatic tab', async () => {
});

test('render manual tab with local user', async () => {
render(<ManuallyLocal />);
render(<ManuallyWithoutTokenLocal />);
expect(screen.getByTestId('Modal')).toMatchSnapshot();
});

test('render manual tab with sso user', async () => {
render(<ManuallySSO />);
render(<ManuallyWithoutTokenSSO />);
expect(screen.getByTestId('Modal')).toMatchSnapshot();
});

test('render manual tab with join token', async () => {
render(<ManuallyWithToken />);
expect(screen.getByTestId('Modal')).toMatchSnapshot();
});
16 changes: 11 additions & 5 deletions packages/teleport/src/Nodes/AddNode/AddNode.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,22 @@ export const Failed = () => (
/>
);

export const ManuallyLocal = () => (
<AddNode {...props} automatic={false} canCreateToken={false} />
export const ManuallyProcessing = () => (
<AddNode {...props} automatic={false} attempt={{ status: 'processing' }} />
);

export const ManuallySSO = () => (
export const ManuallyWithToken = () => <AddNode {...props} automatic={false} />;

export const ManuallyWithoutTokenLocal = () => (
<AddNode {...props} automatic={false} attempt={{ status: 'failed' }} />
);

export const ManuallyWithoutTokenSSO = () => (
<AddNode
{...props}
automatic={false}
canCreateToken={false}
isAuthTypeLocal={false}
attempt={{ status: 'failed' }}
/>
);

Expand All @@ -60,11 +66,11 @@ const props = {
setAutomatic: () => null,
version: '5.0.0-dev',
isEnterprise: true,
canCreateToken: true,
script: 'some bash script',
expiry: '4 hours',
attempt: {
status: 'success',
statusText: '',
} as any,
token: 'some-join-token-hash',
};
6 changes: 5 additions & 1 deletion packages/teleport/src/Nodes/AddNode/AddNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export function AddNode({
version,
attempt,
isAuthTypeLocal,
token,
}: Props & State) {
return (
<Dialog
Expand Down Expand Up @@ -80,14 +81,17 @@ export function AddNode({
expiry={expiry}
createJoinToken={createJoinToken}
attempt={attempt}
mb={3}
/>
)}
{!automatic && (
<Manually
user={user}
version={version}
isAuthTypeLocal={isAuthTypeLocal}
joinToken={token}
expiry={expiry}
createJoinToken={createJoinToken}
attempt={attempt}
/>
)}
</DialogContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import TextSelectCopy from 'teleport/components/TextSelectCopy';
import { Alert, Text, Indicator, Box, ButtonLink } from 'design';

export default function Automatically(props: Props) {
const { script, expiry, createJoinToken, attempt, ...style } = props;
const { script, expiry, createJoinToken, attempt } = props;

if (attempt.status === 'processing') {
return (
Expand All @@ -36,7 +36,7 @@ export default function Automatically(props: Props) {

return (
<>
<Text {...style}>
<Text>
Use below script to add a server to your cluster. This script will
install the Teleport agent to provide secure access to your server.
<Text mt="3">
Expand All @@ -46,7 +46,7 @@ export default function Automatically(props: Props) {
</Text>
</Text>
</Text>
<TextSelectCopy text={script} mb={2} />
<TextSelectCopy text={script} mt={2} />
<Box>
<ButtonLink onClick={createJoinToken}>Regenerate Script</ButtonLink>
</Box>
Expand All @@ -59,5 +59,4 @@ type Props = {
expiry: State['expiry'];
createJoinToken: State['createJoinToken'];
attempt: State['attempt'];
mb: string | number;
};
108 changes: 83 additions & 25 deletions packages/teleport/src/Nodes/AddNode/Manually/Manually.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,20 @@
*/

import React from 'react';
import { Text, Box, Link } from 'design';
import { Text, Box, ButtonLink, Indicator, Link } from 'design';
import TextSelectCopy from 'teleport/components/TextSelectCopy';
import * as links from 'teleport/services/links';
import { State } from './../useAddNode';

export default function Manually({ user, version, isAuthTypeLocal }: Props) {
export default function Manually({
user,
version,
isAuthTypeLocal,
joinToken,
createJoinToken,
expiry,
attempt,
}: Props) {
const { hostname, port } = window.document.location;
const host = `${hostname}:${port || '443'}`;
let tshLoginCmd = `tsh login --proxy=${host}`;
Expand All @@ -28,6 +37,14 @@ export default function Manually({ user, version, isAuthTypeLocal }: Props) {
tshLoginCmd = `${tshLoginCmd} --auth=local --user=${user}`;
}

if (attempt.status === 'processing') {
return (
<Box textAlign="center">
<Indicator />
</Box>
);
}

return (
<>
<Box mb={4}>
Expand All @@ -47,36 +64,77 @@ export default function Manually({ user, version, isAuthTypeLocal }: Props) {
</Link>
</Box>
</Box>
<Box mb={4}>
<Text bold as="span">
Step 2
</Text>
{' - Login to Teleport'}
<TextSelectCopy mt="2" text={tshLoginCmd} />
</Box>
<Box mb={4}>
<Text bold as="span">
Step 3
</Text>
{' - Generate a join token'}
<TextSelectCopy mt="2" text="tctl tokens add --type=node --ttl=1h" />
</Box>
<Box>
<Text bold as="span">
Step 4
</Text>
{` - Start the Teleport agent with the following parameters`}
<TextSelectCopy
mt="2"
text={`teleport start --roles=node --token=[generated-join-token] --auth-server=${host} `}
{attempt.status === 'failed' ? (
<StepsWithoutToken host={host} tshLoginCmd={tshLoginCmd} />
) : (
<StepsWithToken
joinToken={joinToken}
host={host}
createJoinToken={createJoinToken}
expiry={expiry}
/>
</Box>
)}
</>
);
}

const StepsWithoutToken = ({ tshLoginCmd, host }) => (
<>
<Box mb={4}>
<Text bold as="span">
Step 2
</Text>
{' - Login to Teleport'}
<TextSelectCopy mt="2" text={tshLoginCmd} />
</Box>
<Box mb={4}>
<Text bold as="span">
Step 3
</Text>
{' - Generate a join token'}
<TextSelectCopy mt="2" text="tctl tokens add --type=node --ttl=1h" />
</Box>
<Box>
<Text bold as="span">
Step 4
</Text>
{` - Start the Teleport agent with the following parameters`}
<TextSelectCopy
mt="2"
text={`teleport start --roles=node --token=[generated-join-token] --auth-server=${host} `}
/>
</Box>
</>
);

const StepsWithToken = ({ joinToken, host, createJoinToken, expiry }) => (
<Box>
<Text bold as="span">
Step 2
</Text>
{` - Start the Teleport agent with the following parameters`}
<Text mt="1">
The token will be valid for{' '}
<Text bold as={'span'}>
{expiry}.
</Text>
</Text>
<TextSelectCopy
mt="2"
text={`teleport start --roles=node --token=${joinToken} --auth-server=${host} `}
/>
<Box>
<ButtonLink onClick={createJoinToken}>Regenerate Token</ButtonLink>
</Box>
</Box>
);

type Props = {
user: string;
version: string;
isAuthTypeLocal: boolean;
joinToken: string;
expiry: State['expiry'];
createJoinToken: State['createJoinToken'];
attempt: State['attempt'];
};
Loading

0 comments on commit b2a50ab

Please sign in to comment.