Skip to content

Commit

Permalink
Address Crs
Browse files Browse the repository at this point in the history
  • Loading branch information
kimlisa committed Jan 3, 2025
1 parent 0578489 commit 66c6dc3
Show file tree
Hide file tree
Showing 16 changed files with 91 additions and 79 deletions.
3 changes: 2 additions & 1 deletion lib/web/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -884,7 +884,7 @@ func (h *Handler) bindDefaultEndpoints() {
// used for updating a token
h.PUT("/webapi/tokens", h.WithAuth(h.upsertTokenHandle))
// TODO(kimlisa): DELETE IN 19.0 - Replaced by /v2/webapi/token endpoint
// used for creating tokens used during guided discover flows
// MUST delete with related code found in web/packages/teleport/src/services/joinToken/joinToken.ts(fetchJoinToken)
h.POST("/webapi/token", h.WithAuth(h.createTokenForDiscoveryHandle))
// used for creating tokens used during guided discover flows
h.POST("/v2/webapi/token", h.WithAuth(h.createTokenForDiscoveryHandle))
Expand Down Expand Up @@ -1020,6 +1020,7 @@ func (h *Handler) bindDefaultEndpoints() {
h.POST("/webapi/sites/:site/integrations/aws-oidc/:name/ec2", h.WithClusterAuth(h.awsOIDCListEC2))
h.POST("/webapi/sites/:site/integrations/aws-oidc/:name/eksclusters", h.WithClusterAuth(h.awsOIDCListEKSClusters))
// TODO(kimlisa): DELETE IN 19.0 - replaced by /v2/webapi/sites/:site/integrations/aws-oidc/:name/enrolleksclusters
// MUST delete with related code found in web/packages/teleport/src/services/integrations/integrations.ts(enrollEksClusters)
h.POST("/webapi/sites/:site/integrations/aws-oidc/:name/enrolleksclusters", h.WithClusterAuth(h.awsOIDCEnrollEKSClusters))
h.POST("/v2/webapi/sites/:site/integrations/aws-oidc/:name/enrolleksclusters", h.WithClusterAuth(h.awsOIDCEnrollEKSClusters))
h.POST("/webapi/sites/:site/integrations/aws-oidc/:name/ec2ice", h.WithClusterAuth(h.awsOIDCListEC2ICE))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ export const Init = () => {
Init.parameters = {
msw: {
handlers: [
http.post(cfg.api.joinTokenPath, () => HttpResponse.json(rawJoinToken)),
http.post(cfg.api.discoveryJoinToken.createV2, () =>
HttpResponse.json(rawJoinToken)
),
],
},
};
Expand All @@ -74,7 +76,11 @@ export const InitWithLabels = () => {
};
InitWithLabels.parameters = {
msw: {
handlers: [http.post(cfg.api.joinTokenPath, () => HttpResponse.json({}))],
handlers: [
http.post(cfg.api.discoveryJoinToken.createV2, () =>
HttpResponse.json({})
),
],
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ ManualHelmDialogStory.storyName = 'ManualHelmDialog';
ManualHelmDialogStory.parameters = {
msw: {
handlers: [
http.post(cfg.api.joinTokenPath, () => {
http.post(cfg.api.discoveryJoinToken.createV2, () => {
return HttpResponse.json({
id: 'token-id',
suggestedLabels: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export default {
],
};

const tokenHandler = http.post(cfg.api.joinTokenPath, () => {
const tokenHandler = http.post(cfg.api.discoveryJoinToken.createV2, () => {
return HttpResponse.json({
id: 'token-id',
suggestedLabels: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ export const Polling: StoryObj = {
http.get(kubePathWithoutQuery, async () => {
await delay('infinite');
}),
http.post(cfg.api.joinTokenPath, () => HttpResponse.json(rawJoinToken)),
http.post(cfg.api.discoveryJoinToken.createV2, () =>
HttpResponse.json(rawJoinToken)
),
],
},
},
Expand All @@ -80,7 +82,9 @@ export const PollingSuccess: StoryObj = {
http.get(kubePathWithoutQuery, () => {
return HttpResponse.json({ items: [{}] });
}),
http.post(cfg.api.joinTokenPath, () => HttpResponse.json(rawJoinToken)),
http.post(cfg.api.discoveryJoinToken.createV2, () =>
HttpResponse.json(rawJoinToken)
),
],
},
},
Expand All @@ -103,7 +107,9 @@ export const PollingError: StoryObj = {
http.get(kubePathWithoutQuery, async () => {
await delay('infinite');
}),
http.post(cfg.api.joinTokenPath, () => HttpResponse.json(rawJoinToken)),
http.post(cfg.api.discoveryJoinToken.createV2, () =>
HttpResponse.json(rawJoinToken)
),
],
},
},
Expand All @@ -120,7 +126,7 @@ export const Processing: StoryObj = {
parameters: {
msw: {
handlers: [
http.post(cfg.api.joinTokenPath, async () => {
http.post(cfg.api.discoveryJoinToken.createV2, async () => {
await delay('infinite');
}),
],
Expand All @@ -139,7 +145,7 @@ export const Failed: StoryObj = {
parameters: {
msw: {
handlers: [
http.post(cfg.getJoinTokenUrl(), () =>
http.post(cfg.api.discoveryJoinToken.createV2, () =>
HttpResponse.json(
{
error: { message: 'Whoops, something went wrong.' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export const SuccessCloud = () => {
SuccessCloud.parameters = {
msw: {
handlers: [
http.post(cfg.api.joinTokenPath, () =>
http.post(cfg.api.discoveryJoinToken.createV2, () =>
HttpResponse.json({ id: 'token-id' })
),
http.post(cfg.api.discoveryConfigPath, () =>
Expand All @@ -90,7 +90,7 @@ export const SuccessSelfHosted = () => (
SuccessSelfHosted.parameters = {
msw: {
handlers: [
http.post(cfg.api.joinTokenPath, () =>
http.post(cfg.api.discoveryJoinToken.createV2, () =>
HttpResponse.json({ id: 'token-id' })
),
http.post(cfg.api.discoveryConfigPath, () =>
Expand All @@ -107,7 +107,7 @@ export const Loading = () => {
Loading.parameters = {
msw: {
handlers: [
http.post(cfg.api.joinTokenPath, () =>
http.post(cfg.api.discoveryJoinToken.createV2, () =>
HttpResponse.json({ id: 'token-id' })
),
http.post(cfg.api.discoveryConfigPath, () => delay('infinite')),
Expand All @@ -122,7 +122,7 @@ export const Failed = () => {
Failed.parameters = {
msw: {
handlers: [
http.post(cfg.api.joinTokenPath, () =>
http.post(cfg.api.discoveryJoinToken.createV2, () =>
HttpResponse.json({ id: 'token-id' })
),
http.post(cfg.api.discoveryConfigPath, () =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export const Polling: StoryObj = {
http.get(nodesPathWithoutQuery, () => {
return delay('infinite');
}),
http.post(cfg.api.joinTokenPath, () => {
http.post(cfg.api.discoveryJoinToken.createV2, () => {
return HttpResponse.json(joinToken);
}),
],
Expand All @@ -86,7 +86,7 @@ export const PollingSuccess: StoryObj = {
http.get(nodesPathWithoutQuery, () => {
return HttpResponse.json({ items: [{}] });
}),
http.post(cfg.api.joinTokenPath, () => {
http.post(cfg.api.discoveryJoinToken.createV2, () => {
return HttpResponse.json(joinToken);
}),
],
Expand All @@ -111,7 +111,7 @@ export const PollingError: StoryObj = {
http.get(nodesPathWithoutQuery, () => {
return delay('infinite');
}),
http.post(cfg.api.joinTokenPath, () => {
http.post(cfg.api.discoveryJoinToken.createV2, () => {
return HttpResponse.json(joinToken);
}),
],
Expand All @@ -130,7 +130,7 @@ export const Processing: StoryObj = {
parameters: {
msw: {
handlers: [
http.post(cfg.api.joinTokenPath, () => {
http.post(cfg.api.discoveryJoinToken.createV2, () => {
return delay('infinite');
}),
],
Expand All @@ -149,7 +149,7 @@ export const Failed: StoryObj = {
parameters: {
msw: {
handlers: [
http.post(cfg.api.joinTokenPath, () => {
http.post(cfg.api.discoveryJoinToken.createV2, () => {
return HttpResponse.json(
{
error: { message: 'Whoops, something went wrong.' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,10 @@ test('generate command', async () => {

// Test create is still called with 404 ping error.
jest.clearAllMocks();
let error = new ApiError('', { status: 404 } as Response, null);
let error = new ApiError({
message: '',
response: { status: 404 } as Response,
});
spyPing = jest
.spyOn(integrationService, 'pingAwsOidcIntegration')
.mockRejectedValue(error);
Expand All @@ -136,7 +139,7 @@ test('generate command', async () => {

// Test create isn't called with non 404 error
jest.clearAllMocks();
error = new ApiError('', { status: 400 } as Response, null);
error = new ApiError({ message: '', response: { status: 400 } as Response });
spyPing = jest
.spyOn(integrationService, 'pingAwsOidcIntegration')
.mockRejectedValue(error);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,12 @@ describe('session', () => {
});

test('valid session and invalid cookie', async () => {
const mockForbiddenError = new ApiError(
'some error',
{
const mockForbiddenError = new ApiError({
message: 'some error',
response: {
status: 403,
} as Response,
null
);
});

jest
.spyOn(session, 'validateCookieAndSession')
Expand Down
33 changes: 15 additions & 18 deletions web/packages/teleport/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,9 +284,11 @@ const cfg = {
trustedClustersPath: '/v1/webapi/trustedcluster/:name?',
connectMyComputerLoginsPath: '/v1/webapi/connectmycomputer/logins',

// TODO(kimlisa): DELETE IN 19.0 - replaced by /v2/webapi/token
joinTokenPath: '/v1/webapi/token',
joinTokenPathV2: '/v2/webapi/token',
discoveryJoinToken: {
// TODO(kimlisa): DELETE IN 19.0 - replaced by /v2/webapi/token
create: '/v1/webapi/token',
createV2: '/v2/webapi/token',
},
joinTokenYamlPath: '/v1/webapi/tokens/yaml',
joinTokensPath: '/v1/webapi/tokens',
dbScriptPath: '/scripts/:token/install-database.sh',
Expand Down Expand Up @@ -369,11 +371,14 @@ const cfg = {

eksClustersListPath:
'/v1/webapi/sites/:clusterId/integrations/aws-oidc/:name/eksclusters',
// TODO(kimlisa): DELETE IN 19.0 - replaced by /v2/webapi/sites/:clusterId/integrations/aws-oidc/:name/enrolleksclusters
eksEnrollClustersPath:
'/v1/webapi/sites/:clusterId/integrations/aws-oidc/:name/enrolleksclusters',
eksEnrollClustersPathV2:
'/v2/webapi/sites/:clusterId/integrations/aws-oidc/:name/enrolleksclusters',

eks: {
// TODO(kimlisa): DELETE IN 19.0 - replaced by /v2/webapi/sites/:clusterId/integrations/aws-oidc/:name/enrolleksclusters
enroll:
'/v1/webapi/sites/:clusterId/integrations/aws-oidc/:name/enrolleksclusters',
enrollV2:
'/v2/webapi/sites/:clusterId/integrations/aws-oidc/:name/enrolleksclusters',
},

ec2InstancesListPath:
'/v1/webapi/sites/:clusterId/integrations/aws-oidc/:name/ec2',
Expand Down Expand Up @@ -579,14 +584,6 @@ const cfg = {
return cfg.api.joinTokensPath;
},

getJoinTokenUrl() {
return cfg.api.joinTokenPath;
},

getJoinTokenUrlV2() {
return cfg.api.joinTokenPathV2;
},

getJoinTokenYamlUrl() {
return cfg.api.joinTokenYamlPath;
},
Expand Down Expand Up @@ -1092,7 +1089,7 @@ const cfg = {
getEnrollEksClusterUrl(integrationName: string): string {
const clusterId = cfg.proxyCluster;

return generatePath(cfg.api.eksEnrollClustersPath, {
return generatePath(cfg.api.eks.enroll, {
clusterId,
name: integrationName,
});
Expand All @@ -1101,7 +1098,7 @@ const cfg = {
getEnrollEksClusterUrlV2(integrationName: string): string {
const clusterId = cfg.proxyCluster;

return generatePath(cfg.api.eksEnrollClustersPathV2, {
return generatePath(cfg.api.eks.enrollV2, {
clusterId,
name: integrationName,
});
Expand Down
13 changes: 6 additions & 7 deletions web/packages/teleport/src/services/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ const api = {
const message = response.ok
? err.message
: `${response.status} - ${response.url}`;
throw new ApiError(message, response, null, { cause: err });
throw new ApiError({ message, response, opts: { cause: err } });
}

if (response.ok) {
Expand All @@ -177,13 +177,12 @@ const api = {
);
const shouldRetry = isAdminActionMfaError && !mfaResponse;
if (!shouldRetry) {
throw new ApiError(
parseError(json),
throw new ApiError({
message: parseError(json),
response,
parseProxyVersion(json),
undefined,
json.messages
);
proxyVersion: parseProxyVersion(json),
messages: json.messages,
});
}

let mfaResponseForRetry;
Expand Down
36 changes: 23 additions & 13 deletions web/packages/teleport/src/services/api/parseError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
* Currently, the proxy version field is only returned
* with api routes "not found" error.
*
* Used to determine out dated proxies.
* Used to determine outdated proxies.
*
* This response was introduced in v17.2.0.
*/
interface ProxyVersion {
major: number;
Expand All @@ -39,6 +41,17 @@ interface ProxyVersion {
string: string;
}

interface ApiErrorConstructor {
/**
* message is the main error, usually the "cause" of the error.
*/
message: string;
response: Response;
proxyVersion?: ProxyVersion;
opts?: ErrorOptions;
messages?: string[];
}

export default function parseError(json) {
let msg = '';

Expand All @@ -52,10 +65,8 @@ export default function parseError(json) {
return msg;
}

export function parseProxyVersion(json): ProxyVersion | null {
if (json && json.fields && json.fields.proxyVersion) {
return json.fields.proxyVersion;
}
export function parseProxyVersion(json): ProxyVersion | undefined {
return json?.fields?.proxyVersion;
}

export class ApiError extends Error {
Expand All @@ -75,14 +86,13 @@ export class ApiError extends Error {
*/
proxyVersion?: ProxyVersion;

constructor(
message: string,
response: Response,
proxyVersion: ProxyVersion,
opts?: ErrorOptions,
messages?: string[]
) {
// message is the main error, usually the "cause" of the error.
constructor({
message,
response,
proxyVersion,
opts,
messages,
}: ApiErrorConstructor) {
message = message || 'Unknown error';
super(message, opts);
this.response = response;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ test('enrollEksClusters without labels calls v1', async () => {
);
});

test('enrollEksClusters with labbels calls v2', async () => {
test('enrollEksClusters with labels calls v2', async () => {
jest.spyOn(api, 'post').mockResolvedValue({});

await integrationService.enrollEksClusters('integration', {
Expand Down
Loading

0 comments on commit 66c6dc3

Please sign in to comment.