Skip to content
This repository was archived by the owner on Feb 8, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ This mono-repository contains the source code for:

- the web UIs served by the `teleport` server
- [`packages/teleport`](packages/teleport) for the OSS version
- `packages/webapps.e` for the enterprise version
- `packages/webapps.e/teleport` for the enterprise version
- the Electron app of [Teleport Connect](https://goteleport.com/connect/)
- [`packages/teleterm`](packages/teleterm)
- `packages/webapps.e/teleterm` for the enterprise version

The code is organized in terms of independent yarn packages which reside in
the [packages directory](https://github.com/gravitational/webapps/tree/master/packages).
Expand Down
1 change: 1 addition & 0 deletions packages/build/jest/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@ module.exports = {
'^teleport($|/.*)': '<rootDir>/packages/teleport/src/$1',
'^teleterm($|/.*)': '<rootDir>/packages/teleterm/src/$1',
'^e-teleport/(.*)$': '<rootDir>/packages/webapps.e/teleport/src/$1',
'^e-teleterm/(.*)$': '<rootDir>/packages/webapps.e/teleterm/src/$1',
},
};
1 change: 1 addition & 0 deletions packages/build/webpack/webpack.base.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ function createDefaultConfig() {
teleterm: path.join(__dirname, '/../../teleterm/src'),
teleport: path.join(__dirname, '/../../teleport/src'),
'e-teleport': path.join(__dirname, '/../../webapps.e/teleport/src'),
'e-teleterm': path.join(__dirname, '/../../webapps.e/teleterm/src'),
design: path.join(__dirname, '/../../design/src'),
shared: path.join(__dirname, '/../../shared'),
},
Expand Down
20 changes: 20 additions & 0 deletions packages/shared/utils/getDurationText.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { pluralize } from 'teleport/lib/util';

export function getDurationText(hrs: number, mins: number, secs: number) {
if (!hrs && !mins) {
return `${secs} secs`;
}

const hrText = pluralize(hrs, 'hr');
const minText = pluralize(mins, 'min');

if (!hrs) {
return `${mins} ${minText}`;
}

if (hrs && !mins) {
return `${hrs} ${hrText}`;
}

return `${hrs} ${hrText} and ${mins} ${minText}`;
}
228 changes: 219 additions & 9 deletions packages/teleterm/src/services/tshd/createClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { createFileTransferStream } from './createFileTransferStream';
import middleware, { withLogging } from './middleware';
import * as types from './types';
import createAbortController from './createAbortController';
import { AccessRequest, ResourceID } from './v1/access_request_pb';

export default function createClient(
addr: string,
Expand Down Expand Up @@ -48,10 +49,10 @@ export default function createClient(
});
},

async listKubes(clusterUri: string) {
const req = new api.ListKubesRequest().setClusterUri(clusterUri);
async getAllKubes(clusterUri: string) {
const req = new api.GetAllKubesRequest().setClusterUri(clusterUri);
return new Promise<types.Kube[]>((resolve, reject) => {
tshd.listKubes(req, (err, response) => {
tshd.getAllKubes(req, (err, response) => {
if (err) {
reject(err);
} else {
Expand All @@ -61,6 +62,34 @@ export default function createClient(
});
},

async getKubes({
clusterUri,
search,
sort,
query,
searchAsRoles,
startKey,
limit,
}: types.ServerSideParams) {
const req = new api.GetKubesRequest()
.setClusterUri(clusterUri)
.setSearchAsRoles(searchAsRoles)
.setStartKey(startKey)
.setSortBy(`${sort.fieldName}:${sort.dir.toLowerCase()}`)
.setSearch(search)
.setQuery(query)
.setLimit(limit);
return new Promise<types.GetKubesResponse>((resolve, reject) => {
tshd.getKubes(req, (err, response) => {
if (err) {
reject(err);
} else {
resolve(response.toObject());
}
});
});
},

async listGateways() {
const req = new api.ListGatewaysRequest();
return new Promise<types.Gateway[]>((resolve, reject) => {
Expand Down Expand Up @@ -100,10 +129,10 @@ export default function createClient(
});
},

async listDatabases(clusterUri: string) {
const req = new api.ListDatabasesRequest().setClusterUri(clusterUri);
async getAllDatabases(clusterUri: string) {
const req = new api.GetAllDatabasesRequest().setClusterUri(clusterUri);
return new Promise<types.Database[]>((resolve, reject) => {
tshd.listDatabases(req, (err, response) => {
tshd.getAllDatabases(req, (err, response) => {
if (err) {
reject(err);
} else {
Expand All @@ -113,6 +142,34 @@ export default function createClient(
});
},

async getDatabases({
clusterUri,
search,
sort,
query,
searchAsRoles,
startKey,
limit,
}: types.ServerSideParams) {
const req = new api.GetDatabasesRequest()
.setClusterUri(clusterUri)
.setSearchAsRoles(searchAsRoles)
.setStartKey(startKey)
.setSortBy(`${sort.fieldName}:${sort.dir.toLowerCase()}`)
.setSearch(search)
.setQuery(query)
.setLimit(limit);
return new Promise<types.GetDatabasesResponse>((resolve, reject) => {
tshd.getDatabases(req, (err, response) => {
if (err) {
reject(err);
} else {
resolve(response.toObject());
}
});
});
},

async listDatabaseUsers(dbUri: string) {
const req = new api.ListDatabaseUsersRequest().setDbUri(dbUri);
return new Promise<string[]>((resolve, reject) => {
Expand All @@ -126,10 +183,10 @@ export default function createClient(
});
},

async listServers(clusterUri: string) {
const req = new api.ListServersRequest().setClusterUri(clusterUri);
async getAllServers(clusterUri: string) {
const req = new api.GetAllServersRequest().setClusterUri(clusterUri);
return new Promise<types.Server[]>((resolve, reject) => {
tshd.listServers(req, (err, response) => {
tshd.getAllServers(req, (err, response) => {
if (err) {
reject(err);
} else {
Expand All @@ -139,6 +196,159 @@ export default function createClient(
});
},

async getAccessRequest(clusterUri: string, requestId: string) {
const req = new api.GetAccessRequestRequest()
.setClusterUri(clusterUri)
.setAccessRequestId(requestId);
return new Promise<types.AccessRequest>((resolve, reject) => {
tshd.getAccessRequest(req, (err, response) => {
if (err) {
reject(err);
} else {
resolve(response.toObject().request);
}
});
});
},

async getAccessRequests(clusterUri: string) {
const req = new api.GetAccessRequestsRequest().setClusterUri(clusterUri);
return new Promise<types.AccessRequest[]>((resolve, reject) => {
tshd.getAccessRequests(req, (err, response) => {
if (err) {
reject(err);
} else {
resolve(response.toObject().requestsList);
}
});
});
},

async getServers({
clusterUri,
search,
query,
sort,
searchAsRoles,
startKey,
limit,
}: types.ServerSideParams) {
const req = new api.GetServersRequest()
.setClusterUri(clusterUri)
.setSearchAsRoles(searchAsRoles)
.setStartKey(startKey)
.setSortBy(`${sort.fieldName}:${sort.dir.toLowerCase()}`)
.setSearch(search)
.setQuery(query)
.setLimit(limit);
return new Promise<types.GetServersResponse>((resolve, reject) => {
tshd.getServers(req, (err, response) => {
if (err) {
reject(err);
} else {
resolve(response.toObject());
}
});
});
},

async createAccessRequest(params: types.CreateAccessRequestParams) {
const req = new api.CreateAccessRequestRequest()
.setRootClusterUri(params.clusterUri)
.setSuggestedReviewersList(params.suggestedReviewers)
.setRolesList(params.roles)
.setResourceIdsList(
params.resourceIds.map(({ id, clusterName, kind }) => {
const resourceId = new ResourceID();
resourceId.setName(id);
resourceId.setClusterName(clusterName);
resourceId.setKind(kind);
return resourceId;
})
)
.setReason(params.reason);
return new Promise<AccessRequest.AsObject>((resolve, reject) => {
tshd.createAccessRequest(req, (err, response) => {
if (err) {
reject(err);
} else {
resolve(response.toObject().request);
}
});
});
},

async deleteAccessRequest(clusterUri: string, requestId: string) {
const req = new api.DeleteAccessRequestRequest()
.setRootClusterUri(clusterUri)
.setAccessRequestId(requestId);
return new Promise<void>((resolve, reject) => {
tshd.deleteAccessRequest(req, err => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
},

async assumeRole(
clusterUri: string,
requestIds: string[],
dropIds: string[]
) {
const req = new api.AssumeRoleRequest()
.setRootClusterUri(clusterUri)
.setAccessRequestIdsList(requestIds)
.setDropRequestIdsList(dropIds);
return new Promise<void>((resolve, reject) => {
tshd.assumeRole(req, err => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
},

async reviewAccessRequest(
clusterUri: string,
params: types.ReviewAccessRequestParams
) {
const req = new api.ReviewAccessRequestRequest()
.setRootClusterUri(clusterUri)
.setAccessRequestId(params.id)
.setState(params.state)
.setReason(params.reason)
.setRolesList(params.roles);
return new Promise<types.AccessRequest>((resolve, reject) => {
tshd.reviewAccessRequest(req, (err, response) => {
if (err) {
reject(err);
} else {
resolve(response.toObject().request);
}
});
});
},

async getRequestableRoles(clusterUri: string) {
const req = new api.GetRequestableRolesRequest().setClusterUri(
clusterUri
);
return new Promise<string[]>((resolve, reject) => {
tshd.getRequestableRoles(req, (err, response) => {
if (err) {
reject(err);
} else {
resolve(response.toObject().rolesList);
}
});
});
},

async addRootCluster(addr: string) {
const req = new api.AddClusterRequest().setName(addr);
return new Promise<types.Cluster>((resolve, reject) => {
Expand Down
34 changes: 32 additions & 2 deletions packages/teleterm/src/services/tshd/fixtures/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,56 @@ import {
Application,
AuthSettings,
Cluster,
CreateAccessRequestParams,
CreateGatewayParams,
Database,
Gateway,
GetDatabasesResponse,
GetKubesResponse,
GetServersResponse,
Kube,
LoginLocalParams,
LoginPasswordlessParams,
LoginSsoParams,
ReviewAccessRequestParams,
Server,
ServerSideParams,
TshAbortController,
TshAbortSignal,
TshClient,
} from '../types';
import { AccessRequest } from '../v1/access_request_pb';

export class MockTshClient implements TshClient {
listRootClusters: () => Promise<Cluster[]>;
listLeafClusters: (clusterUri: string) => Promise<Cluster[]>;
listApps: (clusterUri: string) => Promise<Application[]>;
listKubes: (clusterUri: string) => Promise<Kube[]>;
listDatabases: (clusterUri: string) => Promise<Database[]>;
getAllKubes: (clusterUri: string) => Promise<Kube[]>;
getKubes: (params: ServerSideParams) => Promise<GetKubesResponse>;
getAllDatabases: (clusterUri: string) => Promise<Database[]>;
getDatabases: (params: ServerSideParams) => Promise<GetDatabasesResponse>;
listDatabaseUsers: (dbUri: string) => Promise<string[]>;
getAllServers: (clusterUri: string) => Promise<Server[]>;
getRequestableRoles: (clusterUri: string) => Promise<string[]>;
getServers: (params: ServerSideParams) => Promise<GetServersResponse>;
assumeRole: (
clusterUri: string,
requestIds: string[],
dropIds: string[]
) => Promise<void>;
deleteAccessRequest: (clusterUri: string, requestId: string) => Promise<void>;
getAccessRequests: (clusterUri: string) => Promise<AccessRequest.AsObject[]>;
getAccessRequest: (
clusterUri: string,
requestId: string
) => Promise<AccessRequest.AsObject>;
reviewAccessRequest: (
clusterUri: string,
params: ReviewAccessRequestParams
) => Promise<AccessRequest.AsObject>;
createAccessRequest: (
params: CreateAccessRequestParams
) => Promise<AccessRequest.AsObject>;
listServers: (clusterUri: string) => Promise<Server[]>;
createAbortController: () => TshAbortController;
addRootCluster: (addr: string) => Promise<Cluster>;
Expand Down
Loading