Skip to content
Merged
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
224 changes: 224 additions & 0 deletions src/gcp/resourceManager.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
import { expect } from "chai";
import * as nock from "nock";
import { addServiceAccountToRoles, serviceAccountHasRoles } from "./resourceManager";
import { Policy } from "./iam";

const PROJECT_ID = "test-project";
const SERVICE_ACCOUNT_NAME = "test-sa";
const FULL_SA_NAME = `projects/${PROJECT_ID}/serviceAccounts/${SERVICE_ACCOUNT_NAME}@${PROJECT_ID}.iam.gserviceaccount.com`;
const MEMBER_NAME = `serviceAccount:${SERVICE_ACCOUNT_NAME}@${PROJECT_ID}.iam.gserviceaccount.com`;

describe("resourceManager", () => {
afterEach(() => {
nock.cleanAll();
});

describe("addServiceAccountToRoles", () => {
it("should add roles when skipAccountLookup is true", async () => {
const initialPolicy: Policy = {
bindings: [],
etag: "etag",
version: 1,
};

const expectedPolicy: Policy = {
bindings: [
{
role: "roles/viewer",
members: [MEMBER_NAME],
},
],
etag: "etag",
version: 1,
};

nock("https://cloudresourcemanager.googleapis.com")
.post(`/v1/projects/${PROJECT_ID}:getIamPolicy`)
.reply(200, initialPolicy);

nock("https://cloudresourcemanager.googleapis.com")
.post(`/v1/projects/${PROJECT_ID}:setIamPolicy`, (body: any) => {

Check warning on line 40 in src/gcp/resourceManager.spec.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unexpected any. Specify a different type
return (
body.updateMask === "bindings" &&

Check warning on line 42 in src/gcp/resourceManager.spec.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unsafe member access .updateMask on an `any` value
JSON.stringify(body.policy) === JSON.stringify(expectedPolicy)

Check warning on line 43 in src/gcp/resourceManager.spec.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unsafe member access .policy on an `any` value
);
})
.reply(200, expectedPolicy);

const result = await addServiceAccountToRoles(
PROJECT_ID,
`${SERVICE_ACCOUNT_NAME}@${PROJECT_ID}.iam.gserviceaccount.com`,
["roles/viewer"],
true,
);

expect(result).to.deep.equal(expectedPolicy);
});

it("should add roles when skipAccountLookup is false", async () => {
const initialPolicy: Policy = {
bindings: [],
etag: "etag",
version: 1,
};

const expectedPolicy: Policy = {
bindings: [
{
role: "roles/viewer",
members: [MEMBER_NAME],
},
],
etag: "etag",
version: 1,
};

nock("https://iam.googleapis.com")
.get(
`/v1/projects/${PROJECT_ID}/serviceAccounts/${SERVICE_ACCOUNT_NAME}@${PROJECT_ID}.iam.gserviceaccount.com`,
)
.reply(200, { name: FULL_SA_NAME });

nock("https://cloudresourcemanager.googleapis.com")
.post(`/v1/projects/${PROJECT_ID}:getIamPolicy`)
.reply(200, initialPolicy);

nock("https://cloudresourcemanager.googleapis.com")
.post(`/v1/projects/${PROJECT_ID}:setIamPolicy`, (body: any) => {

Check warning on line 87 in src/gcp/resourceManager.spec.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unexpected any. Specify a different type
return (
body.updateMask === "bindings" &&

Check warning on line 89 in src/gcp/resourceManager.spec.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unsafe member access .updateMask on an `any` value
JSON.stringify(body.policy) === JSON.stringify(expectedPolicy)

Check warning on line 90 in src/gcp/resourceManager.spec.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unsafe member access .policy on an `any` value
);
})
.reply(200, expectedPolicy);

const result = await addServiceAccountToRoles(
PROJECT_ID,
SERVICE_ACCOUNT_NAME,
["roles/viewer"],
false,
);

expect(result).to.deep.equal(expectedPolicy);
});

it("should not duplicate roles if already present", async () => {
const initialPolicy: Policy = {
bindings: [
{
role: "roles/viewer",
members: [MEMBER_NAME],
},
],
etag: "etag",
version: 1,
};

nock("https://cloudresourcemanager.googleapis.com")
.post(`/v1/projects/${PROJECT_ID}:getIamPolicy`)
.reply(200, initialPolicy);

nock("https://cloudresourcemanager.googleapis.com")
.post(`/v1/projects/${PROJECT_ID}:setIamPolicy`, (body: any) => {

Check warning on line 122 in src/gcp/resourceManager.spec.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unexpected any. Specify a different type
return (
body.updateMask === "bindings" &&

Check warning on line 124 in src/gcp/resourceManager.spec.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unsafe member access .updateMask on an `any` value
JSON.stringify(body.policy) === JSON.stringify(initialPolicy)

Check warning on line 125 in src/gcp/resourceManager.spec.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unsafe member access .policy on an `any` value
);
})
.reply(200, initialPolicy);

const result = await addServiceAccountToRoles(
PROJECT_ID,
`${SERVICE_ACCOUNT_NAME}@${PROJECT_ID}.iam.gserviceaccount.com`,
["roles/viewer"],
true,
);

expect(result).to.deep.equal(initialPolicy);
});
});

describe("serviceAccountHasRoles", () => {
it("should return true if account has all roles", async () => {
const policy: Policy = {
bindings: [
{
role: "roles/viewer",
members: [MEMBER_NAME],
},
{
role: "roles/editor",
members: [MEMBER_NAME],
},
],
etag: "etag",
version: 1,
};

nock("https://cloudresourcemanager.googleapis.com")
.post(`/v1/projects/${PROJECT_ID}:getIamPolicy`)
.reply(200, policy);

const result = await serviceAccountHasRoles(
PROJECT_ID,
`${SERVICE_ACCOUNT_NAME}@${PROJECT_ID}.iam.gserviceaccount.com`,
["roles/viewer", "roles/editor"],
true,
);

expect(result).to.be.true;
});

it("should return false if account is missing a role", async () => {
const policy: Policy = {
bindings: [
{
role: "roles/viewer",
members: [MEMBER_NAME],
},
],
etag: "etag",
version: 1,
};

nock("https://cloudresourcemanager.googleapis.com")
.post(`/v1/projects/${PROJECT_ID}:getIamPolicy`)
.reply(200, policy);

const result = await serviceAccountHasRoles(
PROJECT_ID,
`${SERVICE_ACCOUNT_NAME}@${PROJECT_ID}.iam.gserviceaccount.com`,
["roles/viewer", "roles/editor"],
true,
);

expect(result).to.be.false;
});

it("should return false if role exists but member is missing", async () => {
const policy: Policy = {
bindings: [
{
role: "roles/viewer",
members: ["serviceAccount:other@example.com"],
},
],
etag: "etag",
version: 1,
};

nock("https://cloudresourcemanager.googleapis.com")
.post(`/v1/projects/${PROJECT_ID}:getIamPolicy`)
.reply(200, policy);

const result = await serviceAccountHasRoles(
PROJECT_ID,
`${SERVICE_ACCOUNT_NAME}@${PROJECT_ID}.iam.gserviceaccount.com`,
["roles/viewer"],
true,
);

expect(result).to.be.false;
});
});
});
Loading