Skip to content

Commit

Permalink
Update existing SSH permission requests to match new backend data str…
Browse files Browse the repository at this point in the history
…uctures (#140)

This PR changes the permission request data structures for AWS, Azure,
and Google Cloud SSH to be in line with our most recent changes to the
P0 backend.

These change impact the construction of SSH commands. This latest
version is necessary to continue making valid SSH requests.
  • Loading branch information
GGonryun authored Nov 15, 2024
1 parent e9b2244 commit 0b35f51
Show file tree
Hide file tree
Showing 10 changed files with 76 additions and 64 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@p0security/cli",
"version": "0.11.4",
"version": "0.12.0",
"description": "Execute infra CLI commands with P0 grants",
"main": "index.ts",
"repository": {
Expand Down
41 changes: 26 additions & 15 deletions src/commands/__tests__/ssh.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ You should have received a copy of the GNU General Public License along with @p0
import { TEST_PUBLIC_KEY } from "../../common/__mocks__/keys";
import { fetchCommand } from "../../drivers/api";
import { print1, print2 } from "../../drivers/stdio";
import { AwsSshGenerated, AwsSshPermission } from "../../plugins/aws/types";
import { sshOrScp } from "../../plugins/ssh";
import { mockGetDoc } from "../../testing/firestore";
import { sleep } from "../../util";
Expand All @@ -30,24 +31,34 @@ const mockSshOrScp = sshOrScp as jest.Mock;
const mockPrint1 = print1 as jest.Mock;
const mockPrint2 = print2 as jest.Mock;

const MOCK_REQUEST = {
status: "DONE",
generated: {
const MOCK_PERMISSION: AwsSshPermission = {
provider: "aws",
publicKey: TEST_PUBLIC_KEY,
region: "region",
alias: "alias",
resource: {
account: "accountId",
accountId: "accountId",
arn: "arn",
idcRegion: "idcRegion",
idcId: "idcId",
name: "name",
ssh: {
linuxUserName: "linuxUserName",
},
userName: "userName",
instanceId: "instanceId",
},
permission: {
spec: {
awsResourcePermission: { permission: {} },
instanceId: "instanceId",
accountId: "accountId",
region: "region",
publicKey: TEST_PUBLIC_KEY,
type: "aws",
},
};

const MOCK_GENERATED: AwsSshGenerated = {
resource: {
name: "name",
},
linuxUserName: "linuxUserName",
};

const MOCK_REQUEST = {
status: "DONE",
generated: MOCK_GENERATED,
permission: MOCK_PERMISSION,
};

mockGetDoc({
Expand Down
6 changes: 3 additions & 3 deletions src/commands/shared/ssh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ const pluginToCliRequest = async (
request: Request<PluginSshRequest>,
options?: { debug?: boolean }
): Promise<Request<CliSshRequest>> =>
await SSH_PROVIDERS[request.permission.spec.type].toCliRequest(
await SSH_PROVIDERS[request.permission.provider].toCliRequest(
request as any,
options
);
Expand Down Expand Up @@ -139,7 +139,7 @@ export const provisionRequest = async (
authn,
id
);
if (provisionedRequest.permission.spec.publicKey !== publicKey) {
if (provisionedRequest.permission.publicKey !== publicKey) {
throw "Public key mismatch. Please revoke the request and try again.";
}

Expand All @@ -158,7 +158,7 @@ export const prepareRequest = async (

const { provisionedRequest } = result;

const sshProvider = SSH_PROVIDERS[provisionedRequest.permission.spec.type];
const sshProvider = SSH_PROVIDERS[provisionedRequest.permission.provider];
await sshProvider.ensureInstall();

const cliRequest = await pluginToCliRequest(provisionedRequest, {
Expand Down
9 changes: 4 additions & 5 deletions src/plugins/aws/ssh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,10 @@ export const awsSshProvider: SshProvider<

requestToSsh: (request) => {
const { permission, generated } = request;
const { awsResourcePermission, instanceId, accountId, region } =
permission.spec;
const { idcId, idcRegion } = awsResourcePermission.permission;
const { ssh, name } = generated;
const { linuxUserName } = ssh;
const { resource, region } = permission;
const { idcId, idcRegion, instanceId, accountId } = resource;
const { linuxUserName, resource: generatedResource } = generated;
const { name } = generatedResource;
const common = { linuxUserName, accountId, region, id: instanceId };
return !idcId || !idcRegion
? { ...common, role: name, type: "aws", access: "role" }
Expand Down
30 changes: 14 additions & 16 deletions src/plugins/aws/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,27 +62,25 @@ export type AwsConfig = {

// -- Specific AWS permission types

export type AwsSshPermission = {
spec: CommonSshPermissionSpec & {
instanceId: string;
export type AwsSshPermission = CommonSshPermissionSpec & {
provider: "aws";
region: string;
alias: string;
resource: {
account: string;
accountId: string;
region: string;
type: "aws";
awsResourcePermission: {
permission: {
idcId?: string;
idcRegion?: string;
};
};
arn: string;
idcId: string;
idcRegion: string;
instanceId: string;
name: string;
userName: string;
};
type: "session";
};

export type AwsSshGenerated = {
name: string;
ssh: {
linuxUserName: string;
};
resource: { name: string };
linuxUserName: string;
};

export type AwsSshPermissionSpec = PermissionSpec<
Expand Down
9 changes: 3 additions & 6 deletions src/plugins/azure/ssh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ export const azureSshProvider: SshProvider<
// TODO: Placeholder
requestToSsh: (request) => ({
type: "azure",
id: request.permission.spec.instanceId,
instanceId: request.permission.spec.instanceId,
id: request.permission.resource.instanceId,
instanceId: request.permission.resource.instanceId,
linuxUserName: request.cliLocalData.linuxUserName,
}),

Expand All @@ -69,10 +69,7 @@ export const azureSshProvider: SshProvider<
toCliRequest: async (request, options) => ({
...request,
cliLocalData: {
linuxUserName: await importSshKey(
request.permission.spec.publicKey,
options
),
linuxUserName: await importSshKey(request.permission.publicKey, options),
},
}),
};
17 changes: 14 additions & 3 deletions src/plugins/azure/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,20 @@ export type AzureSsh = CliPermissionSpec<
{ linuxUserName: string }
>;

export type AzureSshPermission = {
type: "session";
spec: CommonSshPermissionSpec & AzureNodeSpec;
export type AzureSshPermission = CommonSshPermissionSpec & {
provider: "azure";
destination: string;
parent: string | undefined;
group: string | undefined;
resource: {
instanceName: string;
instanceId: string;
subscriptionId: string;
subscriptionName: string;
resourceGroupId: string;
region: string;
networkInterfaceIds: string[];
};
};

// TODO: Placeholder; probably wrong
Expand Down
11 changes: 4 additions & 7 deletions src/plugins/google/ssh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,9 @@ export const gcpSshProvider: SshProvider<

requestToSsh: (request) => {
return {
id: request.permission.spec.instanceName,
projectId: request.permission.spec.projectId,
zone: request.permission.spec.zone,
id: request.permission.resource.instanceName,
projectId: request.permission.resource.projectId,
zone: request.permission.zone,
linuxUserName: request.cliLocalData.linuxUserName,
type: "gcloud",
};
Expand All @@ -120,10 +120,7 @@ export const gcpSshProvider: SshProvider<
toCliRequest: async (request, options) => ({
...request,
cliLocalData: {
linuxUserName: await importSshKey(
request.permission.spec.publicKey,
options
),
linuxUserName: await importSshKey(request.permission.publicKey, options),
},
}),
};
11 changes: 5 additions & 6 deletions src/plugins/google/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,13 @@ import { PermissionSpec } from "../../types/request";
import { CliPermissionSpec } from "../../types/ssh";
import { CommonSshPermissionSpec } from "../ssh/types";

export type GcpSshPermission = {
spec: CommonSshPermissionSpec & {
export type GcpSshPermission = CommonSshPermissionSpec & {
provider: "gcloud";
zone: string;
resource: {
instanceName: string;
projectId: string;
zone: string;
type: "gcloud";
};
type: "session";
};

export type GcpSshPermissionSpec = PermissionSpec<"ssh", GcpSshPermission>;
Expand All @@ -30,11 +29,11 @@ export type GcpSsh = CliPermissionSpec<
>;

export type GcpSshRequest = {
type: "gcloud";
linuxUserName: string;
projectId: string;
zone: string;
id: string;
type: "gcloud";
};

type PosixAccount = {
Expand Down
4 changes: 2 additions & 2 deletions src/types/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ This file is part of @p0security/cli
You should have received a copy of the GNU General Public License along with @p0security/cli. If not, see <https://www.gnu.org/licenses/>.
**/
import { K8sPermissionSpec } from "../plugins/kubeconfig/types";
import { PluginSshRequest } from "./ssh";
import { PluginSshRequest, SupportedSshProvider } from "./ssh";

export const DONE_STATUSES = ["DONE", "DONE_NOTIFIED"] as const;
export const DENIED_STATUSES = ["DENIED", "DENIED_NOTIFIED"] as const;
Expand All @@ -21,7 +21,7 @@ export const ERROR_STATUSES = [

export type PermissionSpec<
K extends string,
P extends { type: string },
P extends { provider: SupportedSshProvider } | { type: string },
G extends object | undefined = undefined,
> = {
type: K;
Expand Down

0 comments on commit 0b35f51

Please sign in to comment.