cdk-rds-sql 7.3.0 → 7.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jsii +8 -8
- package/AGENTS.md +5 -6
- package/CLAUDE.md +2 -6
- package/lib/database.js +1 -1
- package/lib/handler/handler.js +60 -52
- package/lib/iam-grant.d.ts +0 -1
- package/lib/iam-grant.js +2 -12
- package/lib/provider.js +1 -1
- package/lib/role.js +1 -1
- package/lib/schema.js +1 -1
- package/lib/sql.js +1 -1
- package/package.json +1 -1
- package/lambda/engine.abstract.ts +0 -121
- package/lambda/engine.dsql.ts +0 -386
- package/lambda/engine.factory.ts +0 -23
- package/lambda/engine.mysql.test.ts +0 -228
- package/lambda/engine.mysql.ts +0 -256
- package/lambda/engine.postgresql.test.ts +0 -151
- package/lambda/engine.postgresql.ts +0 -336
- package/lambda/handler.mysql.test.ts +0 -349
- package/lambda/handler.postgresql.test.ts +0 -338
- package/lambda/handler.test.ts +0 -164
- package/lambda/handler.ts +0 -390
- package/lambda/types.ts +0 -85
- package/lambda/util.ts +0 -186
|
@@ -1,338 +0,0 @@
|
|
|
1
|
-
import { SecretsManagerClient } from "@aws-sdk/client-secrets-manager"
|
|
2
|
-
import { Client, ClientConfig } from "pg"
|
|
3
|
-
import { GenericContainer, StartedTestContainer } from "testcontainers"
|
|
4
|
-
import { handler } from "./handler"
|
|
5
|
-
import {
|
|
6
|
-
createRequest,
|
|
7
|
-
updateRequest,
|
|
8
|
-
deleteRequest,
|
|
9
|
-
schemaExists,
|
|
10
|
-
roleExists,
|
|
11
|
-
databaseExists,
|
|
12
|
-
databaseOwnerIs,
|
|
13
|
-
rowCount,
|
|
14
|
-
roleGrantedForSchema,
|
|
15
|
-
} from "./util"
|
|
16
|
-
|
|
17
|
-
jest.mock("@aws-sdk/client-secrets-manager")
|
|
18
|
-
const SecretsManagerClientMock = SecretsManagerClient as jest.MockedClass<
|
|
19
|
-
typeof SecretsManagerClient
|
|
20
|
-
>
|
|
21
|
-
SecretsManagerClientMock.prototype.send.mockImplementation(() => {
|
|
22
|
-
return {
|
|
23
|
-
SecretString: JSON.stringify({
|
|
24
|
-
host: pgHost,
|
|
25
|
-
port: pgPort,
|
|
26
|
-
username: DB_MASTER_USERNAME,
|
|
27
|
-
password: DB_MASTER_PASSWORD,
|
|
28
|
-
dbname: DB_DEFAULT_DB,
|
|
29
|
-
engine: "postgres",
|
|
30
|
-
dbClusterIdentifier: "dummy",
|
|
31
|
-
}),
|
|
32
|
-
}
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
const DB_PORT = 5432
|
|
36
|
-
const DB_MASTER_USERNAME = "pgroot"
|
|
37
|
-
const DB_MASTER_PASSWORD = "masterpwd"
|
|
38
|
-
const DB_DEFAULT_DB = "dummy"
|
|
39
|
-
|
|
40
|
-
let pgContainer: StartedTestContainer
|
|
41
|
-
let pgHost: string
|
|
42
|
-
let pgPort: number
|
|
43
|
-
|
|
44
|
-
beforeAll(async () => {
|
|
45
|
-
process.env.LOGGER = "true"
|
|
46
|
-
process.env.SSL = "false"
|
|
47
|
-
process.env.CONNECTION_TIMEOUT = "5000"
|
|
48
|
-
pgContainer = await new GenericContainer("postgres:15")
|
|
49
|
-
.withExposedPorts(DB_PORT)
|
|
50
|
-
.withEnvironment({
|
|
51
|
-
POSTGRES_USER: DB_MASTER_USERNAME,
|
|
52
|
-
POSTGRES_PASSWORD: DB_MASTER_PASSWORD,
|
|
53
|
-
POSTGRES_DB: DB_DEFAULT_DB,
|
|
54
|
-
})
|
|
55
|
-
.start()
|
|
56
|
-
pgHost = pgContainer.getHost()
|
|
57
|
-
pgPort = pgContainer.getMappedPort(DB_PORT)
|
|
58
|
-
}, 60000)
|
|
59
|
-
|
|
60
|
-
afterAll(async () => {
|
|
61
|
-
if (pgContainer) {
|
|
62
|
-
await pgContainer.stop()
|
|
63
|
-
}
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
beforeEach(async () => {
|
|
67
|
-
jest.clearAllMocks()
|
|
68
|
-
|
|
69
|
-
// Clean up databases, schemas, and roles created by tests
|
|
70
|
-
const client = new Client({
|
|
71
|
-
host: pgHost,
|
|
72
|
-
port: pgPort,
|
|
73
|
-
database: DB_DEFAULT_DB,
|
|
74
|
-
user: DB_MASTER_USERNAME,
|
|
75
|
-
password: DB_MASTER_PASSWORD,
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
await client.connect()
|
|
79
|
-
|
|
80
|
-
try {
|
|
81
|
-
// Drop all databases except system ones and default
|
|
82
|
-
const databases = await client.query(
|
|
83
|
-
"SELECT datname FROM pg_database WHERE datistemplate = false AND datname != $1",
|
|
84
|
-
[DB_DEFAULT_DB]
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
for (const db of databases.rows) {
|
|
88
|
-
await client.query(`DROP DATABASE IF EXISTS "${db.datname}"`)
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Drop all schemas except system ones
|
|
92
|
-
const schemas = await client.query(
|
|
93
|
-
"SELECT schema_name FROM information_schema.schemata WHERE schema_name NOT IN ('information_schema', 'pg_catalog', 'pg_toast', 'public')"
|
|
94
|
-
)
|
|
95
|
-
|
|
96
|
-
for (const schema of schemas.rows) {
|
|
97
|
-
await client.query(`DROP SCHEMA IF EXISTS "${schema.schema_name}" CASCADE`)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Drop all roles except system ones
|
|
101
|
-
const roles = await client.query(
|
|
102
|
-
"SELECT rolname FROM pg_roles WHERE rolname NOT LIKE 'pg_%' AND rolname != $1",
|
|
103
|
-
[DB_MASTER_USERNAME]
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
for (const role of roles.rows) {
|
|
107
|
-
await client.query(`DROP ROLE IF EXISTS "${role.rolname}"`)
|
|
108
|
-
}
|
|
109
|
-
} finally {
|
|
110
|
-
await client.end()
|
|
111
|
-
}
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
//jest.setTimeout(ms("15s"))
|
|
115
|
-
|
|
116
|
-
test("schema", async () => {
|
|
117
|
-
const oldSchemaName = "test"
|
|
118
|
-
const newSchemaName = "test2"
|
|
119
|
-
const create = createRequest("schema", oldSchemaName)
|
|
120
|
-
await handler(create)
|
|
121
|
-
expect(SecretsManagerClientMock.prototype.send).toHaveBeenCalledTimes(1)
|
|
122
|
-
|
|
123
|
-
const client = await newClient()
|
|
124
|
-
try {
|
|
125
|
-
expect(await schemaExists(client, oldSchemaName)).toEqual(true)
|
|
126
|
-
const update = updateRequest("schema", oldSchemaName, newSchemaName)
|
|
127
|
-
await handler(update)
|
|
128
|
-
expect(await schemaExists(client, oldSchemaName)).toEqual(false)
|
|
129
|
-
expect(await schemaExists(client, newSchemaName)).toEqual(true)
|
|
130
|
-
|
|
131
|
-
// CloudFormation will send a delete afterward, so test that too
|
|
132
|
-
const remove = deleteRequest("schema", newSchemaName)
|
|
133
|
-
await handler(remove)
|
|
134
|
-
expect(await schemaExists(client, newSchemaName)).toEqual(false)
|
|
135
|
-
|
|
136
|
-
// create role for testing
|
|
137
|
-
const roleName = "schematest"
|
|
138
|
-
const createRole = createRequest("role", roleName, {
|
|
139
|
-
PasswordArn: "arn:aws:secretsmanager:us-east-1:123456789:secret:dummy",
|
|
140
|
-
DatabaseName: "postgres",
|
|
141
|
-
})
|
|
142
|
-
await handler(createRole)
|
|
143
|
-
|
|
144
|
-
const createWithRole = createRequest("schema", oldSchemaName, {
|
|
145
|
-
RoleName: roleName,
|
|
146
|
-
})
|
|
147
|
-
await handler(createWithRole)
|
|
148
|
-
expect(await roleGrantedForSchema(client, oldSchemaName, roleName)).toEqual(true)
|
|
149
|
-
const updateWithRole = updateRequest("schema", oldSchemaName, newSchemaName, {
|
|
150
|
-
RoleName: roleName,
|
|
151
|
-
})
|
|
152
|
-
await handler(updateWithRole)
|
|
153
|
-
expect(await roleGrantedForSchema(client, oldSchemaName, roleName)).toEqual(false)
|
|
154
|
-
expect(await roleGrantedForSchema(client, newSchemaName, roleName)).toEqual(true)
|
|
155
|
-
const removeWithRole = deleteRequest("schema", newSchemaName, {
|
|
156
|
-
RoleName: roleName,
|
|
157
|
-
})
|
|
158
|
-
await handler(removeWithRole)
|
|
159
|
-
expect(await roleGrantedForSchema(client, newSchemaName, roleName)).toEqual(false)
|
|
160
|
-
|
|
161
|
-
const removeRole = deleteRequest("role", roleName, {
|
|
162
|
-
DatabaseName: "postgres",
|
|
163
|
-
})
|
|
164
|
-
await handler(removeRole)
|
|
165
|
-
} finally {
|
|
166
|
-
await client.end()
|
|
167
|
-
}
|
|
168
|
-
})
|
|
169
|
-
|
|
170
|
-
test("role with existing database", async () => {
|
|
171
|
-
const oldRoleName = "example"
|
|
172
|
-
const newRoleName = "example2"
|
|
173
|
-
const create = createRequest("role", oldRoleName, {
|
|
174
|
-
PasswordArn: "arn:aws:secretsmanager:us-east-1:123456789:secret:dummy",
|
|
175
|
-
DatabaseName: "postgres",
|
|
176
|
-
})
|
|
177
|
-
await handler(create)
|
|
178
|
-
expect(SecretsManagerClientMock.prototype.send).toHaveBeenCalledTimes(2)
|
|
179
|
-
const client = await newClient()
|
|
180
|
-
try {
|
|
181
|
-
expect(await roleExists(client, oldRoleName)).toEqual(true)
|
|
182
|
-
|
|
183
|
-
// Attempt to connect as this role
|
|
184
|
-
const client2 = await newClient({
|
|
185
|
-
user: oldRoleName,
|
|
186
|
-
})
|
|
187
|
-
await client2.end()
|
|
188
|
-
|
|
189
|
-
const update = updateRequest("role", oldRoleName, newRoleName, {
|
|
190
|
-
PasswordArn: "arn:aws:secretsmanager:us-east-1:123456789:secret:dummy",
|
|
191
|
-
DatabaseName: "postgres",
|
|
192
|
-
})
|
|
193
|
-
await handler(update)
|
|
194
|
-
expect(await roleExists(client, oldRoleName)).toEqual(false)
|
|
195
|
-
expect(await roleExists(client, newRoleName)).toEqual(true)
|
|
196
|
-
|
|
197
|
-
// CloudFormation will send a delete afterward as we change the
|
|
198
|
-
// physical id, so test that too
|
|
199
|
-
const remove = deleteRequest("role", oldRoleName, {
|
|
200
|
-
DatabaseName: "postgres",
|
|
201
|
-
})
|
|
202
|
-
await handler(remove)
|
|
203
|
-
expect(await roleExists(client, oldRoleName)).toEqual(false)
|
|
204
|
-
} finally {
|
|
205
|
-
await client.end()
|
|
206
|
-
}
|
|
207
|
-
})
|
|
208
|
-
|
|
209
|
-
test("role without database", async () => {
|
|
210
|
-
const roleName = "example"
|
|
211
|
-
const create = createRequest("role", roleName, {
|
|
212
|
-
PasswordArn: "arn:aws:secretsmanager:us-east-1:123456789:secret:dummy",
|
|
213
|
-
})
|
|
214
|
-
await handler(create)
|
|
215
|
-
expect(SecretsManagerClientMock.prototype.send).toHaveBeenCalledTimes(2)
|
|
216
|
-
const client = await newClient()
|
|
217
|
-
try {
|
|
218
|
-
expect(await roleExists(client, roleName)).toEqual(true)
|
|
219
|
-
} finally {
|
|
220
|
-
await client.end()
|
|
221
|
-
}
|
|
222
|
-
})
|
|
223
|
-
|
|
224
|
-
test("change role password", async () => {
|
|
225
|
-
const roleName = "example"
|
|
226
|
-
const create = createRequest("role", roleName, {
|
|
227
|
-
PasswordArn: "arn:aws:secretsmanager:us-east-1:123456789:secret:dummy",
|
|
228
|
-
})
|
|
229
|
-
await handler(create)
|
|
230
|
-
expect(SecretsManagerClientMock.prototype.send).toHaveBeenCalledTimes(2)
|
|
231
|
-
const client = await newClient()
|
|
232
|
-
try {
|
|
233
|
-
expect(await roleExists(client, roleName)).toEqual(true)
|
|
234
|
-
const update = updateRequest("role", roleName, roleName, {
|
|
235
|
-
PasswordArn: "arn:aws:secretsmanager:us-east-1:123456789:secret:dummy",
|
|
236
|
-
})
|
|
237
|
-
await handler(update)
|
|
238
|
-
} finally {
|
|
239
|
-
await client.end()
|
|
240
|
-
}
|
|
241
|
-
})
|
|
242
|
-
|
|
243
|
-
test("database", async () => {
|
|
244
|
-
const oldDatabaseName = "mydb"
|
|
245
|
-
const newDatabaseName = "mydb2"
|
|
246
|
-
const create = createRequest("database", oldDatabaseName)
|
|
247
|
-
await handler(create)
|
|
248
|
-
expect(SecretsManagerClientMock.prototype.send).toHaveBeenCalledTimes(1)
|
|
249
|
-
const client = await newClient()
|
|
250
|
-
try {
|
|
251
|
-
expect(await databaseExists(client, oldDatabaseName)).toEqual(true)
|
|
252
|
-
expect(await databaseOwnerIs(client, oldDatabaseName, DB_MASTER_USERNAME)).toEqual(
|
|
253
|
-
true
|
|
254
|
-
)
|
|
255
|
-
const update = updateRequest("database", oldDatabaseName, newDatabaseName)
|
|
256
|
-
await handler(update)
|
|
257
|
-
expect(await databaseExists(client, oldDatabaseName)).toEqual(false)
|
|
258
|
-
expect(await databaseExists(client, newDatabaseName)).toEqual(true)
|
|
259
|
-
|
|
260
|
-
// CloudFormation will send a delete afterward, so test that too
|
|
261
|
-
const remove = deleteRequest("database", oldDatabaseName)
|
|
262
|
-
await handler(remove)
|
|
263
|
-
expect(await databaseExists(client, oldDatabaseName)).toEqual(false)
|
|
264
|
-
} finally {
|
|
265
|
-
await client.end()
|
|
266
|
-
}
|
|
267
|
-
})
|
|
268
|
-
|
|
269
|
-
test("database with owner", async () => {
|
|
270
|
-
const databaseName = "mydb"
|
|
271
|
-
const roleName = "example"
|
|
272
|
-
const create_role = createRequest("role", roleName, {
|
|
273
|
-
PasswordArn: "arn:aws:secretsmanager:us-east-1:123456789:secret:dummy",
|
|
274
|
-
DatabaseName: "mydb", // database does not exist yet
|
|
275
|
-
})
|
|
276
|
-
await handler(create_role)
|
|
277
|
-
const create_db = createRequest("database", databaseName, { Owner: "example" })
|
|
278
|
-
await handler(create_db)
|
|
279
|
-
const client = await newClient()
|
|
280
|
-
try {
|
|
281
|
-
expect(await databaseExists(client, databaseName)).toEqual(true)
|
|
282
|
-
expect(await databaseOwnerIs(client, databaseName, roleName)).toEqual(true)
|
|
283
|
-
const create_table = createRequest("sql", "", {
|
|
284
|
-
DatabaseName: databaseName,
|
|
285
|
-
Statement: "create table t(i int)",
|
|
286
|
-
})
|
|
287
|
-
await handler(create_table)
|
|
288
|
-
|
|
289
|
-
// Verify we can login as owner
|
|
290
|
-
{
|
|
291
|
-
const client2 = await newClient({
|
|
292
|
-
user: roleName,
|
|
293
|
-
database: databaseName,
|
|
294
|
-
})
|
|
295
|
-
try {
|
|
296
|
-
expect(await rowCount(client2, "t")).toEqual(0)
|
|
297
|
-
} finally {
|
|
298
|
-
await client2.end()
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
const oldDatabaseName = "mydb"
|
|
303
|
-
const newDatabaseName = "mydb2"
|
|
304
|
-
const update = updateRequest("database", oldDatabaseName, newDatabaseName, {
|
|
305
|
-
Owner: "example",
|
|
306
|
-
})
|
|
307
|
-
await handler(update)
|
|
308
|
-
expect(await databaseExists(client, oldDatabaseName)).toEqual(false)
|
|
309
|
-
expect(await databaseExists(client, newDatabaseName)).toEqual(true)
|
|
310
|
-
|
|
311
|
-
// Verify we can login as owner against renamed database
|
|
312
|
-
{
|
|
313
|
-
const client2 = await newClient({
|
|
314
|
-
user: roleName,
|
|
315
|
-
database: newDatabaseName,
|
|
316
|
-
})
|
|
317
|
-
try {
|
|
318
|
-
expect(await rowCount(client2, "t")).toEqual(0)
|
|
319
|
-
} finally {
|
|
320
|
-
await client2.end()
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
} finally {
|
|
324
|
-
await client.end()
|
|
325
|
-
}
|
|
326
|
-
})
|
|
327
|
-
|
|
328
|
-
const newClient = async (config?: ClientConfig): Promise<Client> => {
|
|
329
|
-
const client = new Client({
|
|
330
|
-
host: pgHost,
|
|
331
|
-
port: pgPort,
|
|
332
|
-
database: config && config.database ? config.database : DB_DEFAULT_DB,
|
|
333
|
-
user: DB_MASTER_USERNAME,
|
|
334
|
-
password: DB_MASTER_PASSWORD,
|
|
335
|
-
})
|
|
336
|
-
await client.connect()
|
|
337
|
-
return client
|
|
338
|
-
}
|
package/lambda/handler.test.ts
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
import { SecretsManagerClient } from "@aws-sdk/client-secrets-manager"
|
|
2
|
-
import { MysqlEngine } from "./engine.mysql"
|
|
3
|
-
import { PostgresqlEngine } from "./engine.postgresql"
|
|
4
|
-
import { handler } from "./handler"
|
|
5
|
-
import { createRequest } from "./util"
|
|
6
|
-
|
|
7
|
-
// Mock the secrets manager client
|
|
8
|
-
jest.mock("@aws-sdk/client-secrets-manager")
|
|
9
|
-
const SecretsManagerClientMock = SecretsManagerClient as jest.MockedClass<
|
|
10
|
-
typeof SecretsManagerClient
|
|
11
|
-
>
|
|
12
|
-
|
|
13
|
-
// Mock the database engines
|
|
14
|
-
jest.mock("./engine.mysql")
|
|
15
|
-
jest.mock("./engine.postgresql")
|
|
16
|
-
|
|
17
|
-
const MockedMysqlEngine = MysqlEngine as jest.MockedClass<typeof MysqlEngine>
|
|
18
|
-
const MockedPostgresqlEngine = PostgresqlEngine as jest.MockedClass<
|
|
19
|
-
typeof PostgresqlEngine
|
|
20
|
-
>
|
|
21
|
-
|
|
22
|
-
describe("Handler CloudFormation Property Conversion", () => {
|
|
23
|
-
let mockMysqlEngine: jest.Mocked<MysqlEngine>
|
|
24
|
-
let mockPostgresqlEngine: jest.Mocked<PostgresqlEngine>
|
|
25
|
-
|
|
26
|
-
beforeEach(() => {
|
|
27
|
-
jest.clearAllMocks()
|
|
28
|
-
|
|
29
|
-
// Mock the engine instances
|
|
30
|
-
mockMysqlEngine = {
|
|
31
|
-
createRole: jest.fn(),
|
|
32
|
-
executeSQL: jest.fn(),
|
|
33
|
-
} as any
|
|
34
|
-
|
|
35
|
-
mockPostgresqlEngine = {
|
|
36
|
-
createRole: jest.fn(),
|
|
37
|
-
executeSQL: jest.fn(),
|
|
38
|
-
} as any
|
|
39
|
-
|
|
40
|
-
MockedMysqlEngine.mockImplementation(() => mockMysqlEngine)
|
|
41
|
-
MockedPostgresqlEngine.mockImplementation(() => mockPostgresqlEngine)
|
|
42
|
-
|
|
43
|
-
// Mock secrets manager to return MySQL engine
|
|
44
|
-
SecretsManagerClientMock.prototype.send.mockImplementation(() => {
|
|
45
|
-
return Promise.resolve({
|
|
46
|
-
SecretString: JSON.stringify({
|
|
47
|
-
host: "localhost",
|
|
48
|
-
port: 3306,
|
|
49
|
-
username: "root",
|
|
50
|
-
password: "password",
|
|
51
|
-
dbname: "test",
|
|
52
|
-
engine: "mysql",
|
|
53
|
-
}),
|
|
54
|
-
})
|
|
55
|
-
})
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
describe("EnableIamAuth property conversion", () => {
|
|
59
|
-
it("should convert string 'false' to boolean false", async () => {
|
|
60
|
-
mockMysqlEngine.createRole.mockResolvedValue(["CREATE USER test"])
|
|
61
|
-
mockMysqlEngine.executeSQL.mockResolvedValue({})
|
|
62
|
-
|
|
63
|
-
// Create a request with EnableIamAuth as string 'false' (simulating CloudFormation)
|
|
64
|
-
const request = createRequest("role", "testuser", {
|
|
65
|
-
EnableIamAuth: "false",
|
|
66
|
-
PasswordArn: "arn:aws:secretsmanager:us-east-1:123456789:secret:dummy",
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
await handler(request)
|
|
70
|
-
|
|
71
|
-
// Verify that createRole was called with boolean false, not string 'false'
|
|
72
|
-
expect(mockMysqlEngine.createRole).toHaveBeenCalledWith(
|
|
73
|
-
"testuser",
|
|
74
|
-
expect.objectContaining({
|
|
75
|
-
EnableIamAuth: false, // Should be converted to boolean false
|
|
76
|
-
PasswordArn: "arn:aws:secretsmanager:us-east-1:123456789:secret:dummy",
|
|
77
|
-
})
|
|
78
|
-
)
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
it("should convert string 'true' to boolean true", async () => {
|
|
82
|
-
mockMysqlEngine.createRole.mockResolvedValue(["CREATE USER test"])
|
|
83
|
-
mockMysqlEngine.executeSQL.mockResolvedValue({})
|
|
84
|
-
|
|
85
|
-
// Create a request with EnableIamAuth as string 'true' (simulating CloudFormation)
|
|
86
|
-
const request = createRequest("role", "testuser", {
|
|
87
|
-
EnableIamAuth: "true", // CloudFormation passes boolean as string
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
await handler(request)
|
|
91
|
-
|
|
92
|
-
// Verify that createRole was called with boolean true, not string 'true'
|
|
93
|
-
expect(mockMysqlEngine.createRole).toHaveBeenCalledWith(
|
|
94
|
-
"testuser",
|
|
95
|
-
expect.objectContaining({
|
|
96
|
-
EnableIamAuth: true, // Should be converted to boolean true
|
|
97
|
-
})
|
|
98
|
-
)
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
it("should handle number 0 correctly", async () => {
|
|
102
|
-
mockMysqlEngine.createRole.mockResolvedValue(["CREATE USER test"])
|
|
103
|
-
mockMysqlEngine.executeSQL.mockResolvedValue({})
|
|
104
|
-
|
|
105
|
-
// Create a request with EnableIamAuth as actual boolean false
|
|
106
|
-
const request = createRequest("role", "testuser", {
|
|
107
|
-
EnableIamAuth: "0",
|
|
108
|
-
PasswordArn: "arn:aws:secretsmanager:us-east-1:123456789:secret:dummy",
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
await handler(request)
|
|
112
|
-
|
|
113
|
-
// Verify that createRole was called with boolean false
|
|
114
|
-
expect(mockMysqlEngine.createRole).toHaveBeenCalledWith(
|
|
115
|
-
"testuser",
|
|
116
|
-
expect.objectContaining({
|
|
117
|
-
EnableIamAuth: false,
|
|
118
|
-
PasswordArn: "arn:aws:secretsmanager:us-east-1:123456789:secret:dummy",
|
|
119
|
-
})
|
|
120
|
-
)
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
it("should handle number 1 correctly", async () => {
|
|
124
|
-
mockMysqlEngine.createRole.mockResolvedValue(["CREATE USER test"])
|
|
125
|
-
mockMysqlEngine.executeSQL.mockResolvedValue({})
|
|
126
|
-
|
|
127
|
-
// Create a request with EnableIamAuth as actual boolean true
|
|
128
|
-
const request = createRequest("role", "testuser", {
|
|
129
|
-
EnableIamAuth: "1",
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
await handler(request)
|
|
133
|
-
|
|
134
|
-
// Verify that createRole was called with boolean true
|
|
135
|
-
expect(mockMysqlEngine.createRole).toHaveBeenCalledWith(
|
|
136
|
-
"testuser",
|
|
137
|
-
expect.objectContaining({
|
|
138
|
-
EnableIamAuth: true,
|
|
139
|
-
})
|
|
140
|
-
)
|
|
141
|
-
})
|
|
142
|
-
|
|
143
|
-
it("should handle undefined EnableIamAuth correctly", async () => {
|
|
144
|
-
mockMysqlEngine.createRole.mockResolvedValue(["CREATE USER test"])
|
|
145
|
-
mockMysqlEngine.executeSQL.mockResolvedValue({})
|
|
146
|
-
|
|
147
|
-
// Create a request without EnableIamAuth property
|
|
148
|
-
const request = createRequest("role", "testuser", {
|
|
149
|
-
PasswordArn: "arn:aws:secretsmanager:us-east-1:123456789:secret:dummy",
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
await handler(request)
|
|
153
|
-
|
|
154
|
-
// Verify that createRole was called without EnableIamAuth
|
|
155
|
-
expect(mockMysqlEngine.createRole).toHaveBeenCalledWith(
|
|
156
|
-
"testuser",
|
|
157
|
-
expect.objectContaining({
|
|
158
|
-
PasswordArn: "arn:aws:secretsmanager:us-east-1:123456789:secret:dummy",
|
|
159
|
-
EnableIamAuth: false,
|
|
160
|
-
})
|
|
161
|
-
)
|
|
162
|
-
})
|
|
163
|
-
})
|
|
164
|
-
})
|