Skip to content

Commit 27c5d55

Browse files
committed
test: add auth-eth tests for IAppTcbPolicy and policy API endpoints
1 parent 945b330 commit 27c5d55

3 files changed

Lines changed: 209 additions & 1 deletion

File tree

kms/auth-eth/test/DstackApp.test.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,51 @@ describe("DstackApp", function () {
127127
});
128128
});
129129

130+
describe("TCB policy (IAppTcbPolicy)", function () {
131+
const testPolicy = '{"version":1,"intel_qal":["policy1"]}';
132+
133+
it("Should return empty string by default", async function () {
134+
expect(await appAuth.tcbPolicy()).to.equal("");
135+
});
136+
137+
it("Should allow owner to set TCB policy", async function () {
138+
await appAuth.setTcbPolicy(testPolicy);
139+
expect(await appAuth.tcbPolicy()).to.equal(testPolicy);
140+
});
141+
142+
it("Should emit TcbPolicySet event", async function () {
143+
await expect(appAuth.setTcbPolicy(testPolicy))
144+
.to.emit(appAuth, "TcbPolicySet")
145+
.withArgs(testPolicy);
146+
});
147+
148+
it("Should allow clearing TCB policy with empty string", async function () {
149+
await appAuth.setTcbPolicy(testPolicy);
150+
await appAuth.setTcbPolicy("");
151+
expect(await appAuth.tcbPolicy()).to.equal("");
152+
});
153+
154+
it("Should prevent non-owners from setting TCB policy", async function () {
155+
await expect(
156+
appAuth.connect(user).setTcbPolicy(testPolicy)
157+
).to.be.revertedWithCustomError(appAuth, "OwnableUnauthorizedAccount");
158+
});
159+
160+
it("Should support IAppTcbPolicy interface (ERC-165)", async function () {
161+
// IAppTcbPolicy interfaceId = tcbPolicy() ^ setTcbPolicy(string)
162+
// We verify via supportsInterface
163+
const iface = new ethers.Interface([
164+
"function tcbPolicy() view returns (string)",
165+
"function setTcbPolicy(string)",
166+
]);
167+
const interfaceId =
168+
BigInt(iface.getFunction("tcbPolicy")!.selector) ^
169+
BigInt(iface.getFunction("setTcbPolicy")!.selector);
170+
const id = "0x" + (interfaceId & BigInt("0xffffffff")).toString(16).padStart(8, "0");
171+
expect(await appAuth.supportsInterface(id)).to.be.true;
172+
});
173+
});
174+
130175
describe("Initialize with device and hash", function () {
131176
let appAuthWithData: DstackApp;
132177
const testDevice = ethers.randomBytes(32);
@@ -251,3 +296,52 @@ describe("DstackApp", function () {
251296
});
252297
});
253298
});
299+
300+
describe("DstackKms TCB policy", function () {
301+
let kmsContract: any;
302+
let owner: SignerWithAddress;
303+
let user: SignerWithAddress;
304+
305+
beforeEach(async function () {
306+
[owner, user] = await ethers.getSigners();
307+
kmsContract = await deployContract(hre, "DstackKms", [
308+
owner.address,
309+
ethers.ZeroAddress,
310+
], true);
311+
});
312+
313+
it("Should return empty string by default", async function () {
314+
expect(await kmsContract.tcbPolicy()).to.equal("");
315+
});
316+
317+
it("Should allow owner to set TCB policy", async function () {
318+
const policy = '{"version":1,"intel_qal":[]}';
319+
await kmsContract.setTcbPolicy(policy);
320+
expect(await kmsContract.tcbPolicy()).to.equal(policy);
321+
});
322+
323+
it("Should emit TcbPolicySet event", async function () {
324+
const policy = '{"version":1}';
325+
await expect(kmsContract.setTcbPolicy(policy))
326+
.to.emit(kmsContract, "TcbPolicySet")
327+
.withArgs(policy);
328+
});
329+
330+
it("Should prevent non-owners from setting TCB policy", async function () {
331+
await expect(
332+
kmsContract.connect(user).setTcbPolicy("test")
333+
).to.be.revertedWithCustomError(kmsContract, "OwnableUnauthorizedAccount");
334+
});
335+
336+
it("Should support IAppTcbPolicy interface (ERC-165)", async function () {
337+
const iface = new ethers.Interface([
338+
"function tcbPolicy() view returns (string)",
339+
"function setTcbPolicy(string)",
340+
]);
341+
const interfaceId =
342+
BigInt(iface.getFunction("tcbPolicy")!.selector) ^
343+
BigInt(iface.getFunction("setTcbPolicy")!.selector);
344+
const id = "0x" + (interfaceId & BigInt("0xffffffff")).toString(16).padStart(8, "0");
345+
expect(await kmsContract.supportsInterface(id)).to.be.true;
346+
});
347+
});

kms/auth-eth/test/ethereum.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,38 @@ describe('EthereumBackend', () => {
8181
expect(result.isAllowed).toBe(false);
8282
});
8383
});
84+
85+
describe('getAppPolicy', () => {
86+
it('should return empty tcbPolicy by default', async () => {
87+
const result = await backend.getAppPolicy(appId);
88+
expect(result.tcbPolicy).toBe('');
89+
});
90+
91+
it('should return set tcbPolicy', async () => {
92+
const policy = '{"version":1,"intel_qal":["test-policy"]}';
93+
await appAuth.setTcbPolicy(policy);
94+
const result = await backend.getAppPolicy(appId);
95+
expect(result.tcbPolicy).toBe(policy);
96+
});
97+
98+
it('should return empty string for address without IAppTcbPolicy', async () => {
99+
const randomAddr = ethers.Wallet.createRandom().address;
100+
const result = await backend.getAppPolicy(randomAddr);
101+
expect(result.tcbPolicy).toBe('');
102+
});
103+
});
104+
105+
describe('getKmsPolicy', () => {
106+
it('should return empty tcbPolicy by default', async () => {
107+
const result = await backend.getKmsPolicy();
108+
expect(result.tcbPolicy).toBe('');
109+
});
110+
111+
it('should return set tcbPolicy', async () => {
112+
const policy = '{"version":1,"intel_qal":[]}';
113+
await kmsContract.setTcbPolicy(policy);
114+
const result = await backend.getKmsPolicy();
115+
expect(result.tcbPolicy).toBe(policy);
116+
});
117+
});
84118
});

kms/auth-eth/test/main.test.ts

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@ import { BootInfo } from '../src/types';
1010
jest.mock('../src/ethereum', () => {
1111
return {
1212
EthereumBackend: jest.fn().mockImplementation(() => ({
13-
checkBoot: jest.fn()
13+
checkBoot: jest.fn(),
14+
getAppPolicy: jest.fn(),
15+
getKmsPolicy: jest.fn(),
16+
getGatewayAppId: jest.fn().mockResolvedValue('0x1234'),
17+
getChainId: jest.fn().mockResolvedValue(1),
18+
getAppImplementation: jest.fn().mockResolvedValue('0x0000000000000000000000000000000000000000'),
1419
}))
1520
};
1621
});
@@ -114,4 +119,79 @@ describe('Server', () => {
114119
expect(result.reason).toMatch(/Test backend error/);
115120
});
116121
});
122+
123+
describe('GET /policy/app/:appId', () => {
124+
it('should return tcbPolicy from backend', async () => {
125+
const policy = '{"version":1,"intel_qal":["test"]}';
126+
app.ethereum.getAppPolicy = jest.fn().mockResolvedValue({ tcbPolicy: policy });
127+
128+
const response = await app.inject({
129+
method: 'GET',
130+
url: '/policy/app/0x9012345678901234567890123456789012345678',
131+
});
132+
133+
expect(response.statusCode).toBe(200);
134+
const result = JSON.parse(response.payload);
135+
expect(result.tcbPolicy).toBe(policy);
136+
});
137+
138+
it('should return empty tcbPolicy when none set', async () => {
139+
app.ethereum.getAppPolicy = jest.fn().mockResolvedValue({ tcbPolicy: '' });
140+
141+
const response = await app.inject({
142+
method: 'GET',
143+
url: '/policy/app/0x9012345678901234567890123456789012345678',
144+
});
145+
146+
expect(response.statusCode).toBe(200);
147+
const result = JSON.parse(response.payload);
148+
expect(result.tcbPolicy).toBe('');
149+
});
150+
});
151+
152+
describe('GET /policy/kms', () => {
153+
it('should return tcbPolicy from backend', async () => {
154+
const policy = '{"version":1,"intel_qal":[]}';
155+
app.ethereum.getKmsPolicy = jest.fn().mockResolvedValue({ tcbPolicy: policy });
156+
157+
const response = await app.inject({
158+
method: 'GET',
159+
url: '/policy/kms',
160+
});
161+
162+
expect(response.statusCode).toBe(200);
163+
const result = JSON.parse(response.payload);
164+
expect(result.tcbPolicy).toBe(policy);
165+
});
166+
167+
it('should return empty tcbPolicy when none set', async () => {
168+
app.ethereum.getKmsPolicy = jest.fn().mockResolvedValue({ tcbPolicy: '' });
169+
170+
const response = await app.inject({
171+
method: 'GET',
172+
url: '/policy/kms',
173+
});
174+
175+
expect(response.statusCode).toBe(200);
176+
const result = JSON.parse(response.payload);
177+
expect(result.tcbPolicy).toBe('');
178+
});
179+
});
180+
181+
describe('GET /', () => {
182+
it('should return server info', async () => {
183+
const response = await app.inject({
184+
method: 'GET',
185+
url: '/',
186+
});
187+
188+
expect(response.statusCode).toBe(200);
189+
const result = JSON.parse(response.payload);
190+
expect(result.status).toBe('ok');
191+
expect(result).toHaveProperty('kmsContractAddr');
192+
expect(result).toHaveProperty('gatewayAppId');
193+
expect(result).toHaveProperty('chainId');
194+
expect(result).toHaveProperty('appImplementation');
195+
});
196+
});
117197
});

0 commit comments

Comments
 (0)