Skip to content

Commit c345df8

Browse files
committed
fix: add apigw auth config
1 parent 8a993c7 commit c345df8

File tree

2 files changed

+189
-19
lines changed

2 files changed

+189
-19
lines changed

src/baas/apigw/index.js

Lines changed: 175 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -238,9 +238,7 @@ class Apigw {
238238
return secretIdsOutput
239239
}
240240

241-
async setupApiUsagePlan({ endpoint }) {
242-
const { usagePlan = {} } = endpoint
243-
241+
async setupApiUsagePlan({ usagePlan }) {
244242
const usageInputs = {
245243
usagePlanName: usagePlan.usagePlanName || '',
246244
usagePlanDesc: usagePlan.usagePlanDesc || '',
@@ -249,15 +247,16 @@ class Apigw {
249247
}
250248

251249
const usagePlanOutput = {
252-
created: false,
253-
id: usagePlan.usagePlanId
250+
created: usagePlan.created || false,
251+
id: usagePlan.id
254252
}
255253

256-
if (!usagePlan.usagePlanId) {
257-
usagePlanOutput.id = await this.request({
254+
if (!usagePlan.id) {
255+
const createUsagePlan = await this.request({
258256
Action: 'CreateUsagePlan',
259257
...usageInputs
260258
})
259+
usagePlanOutput.id = createUsagePlan.usagePlanId
261260
usagePlanOutput.created = true
262261
console.debug(`Usage plan with ID ${usagePlanOutput.id} created.`)
263262
} else {
@@ -272,6 +271,35 @@ class Apigw {
272271
return usagePlanOutput
273272
}
274273

274+
/**
275+
* get all unbound secretids
276+
*/
277+
async getUnboundSecretIds({ usagePlanId, secretIds }) {
278+
const getAllBoundSecrets = async (res = [], { limit, offset = 0 }) => {
279+
const { secretIdList } = await this.request({
280+
Action: 'DescribeUsagePlanSecretIds',
281+
usagePlanId,
282+
limit,
283+
offset
284+
})
285+
if (secretIdList.length < limit) {
286+
return res
287+
}
288+
return getAllBoundSecrets(res, { limit, offset: offset + secretIdList.length })
289+
}
290+
const allBoundSecretObjs = await getAllBoundSecrets([], { limit: 100 })
291+
const allBoundSecretIds = allBoundSecretObjs.map((item) => item.secretId)
292+
const unboundSecretIds = secretIds.filter((item) => {
293+
if (allBoundSecretIds.indexOf(item) === -1) {
294+
return true
295+
}
296+
console.log(`Usage plan ${usagePlanId} secret id ${item} already bound`)
297+
return false
298+
})
299+
return unboundSecretIds
300+
}
301+
302+
// bind custom domains
275303
async bindCustomDomain({ serviceId, subDomain, inputs }) {
276304
const { customDomains, oldState = {} } = inputs
277305
// 1. unbind all custom domain
@@ -338,8 +366,44 @@ class Apigw {
338366
return customDomainOutput
339367
}
340368

369+
// bind environment fo usage plan
370+
async bindUsagePlanEnvironment({
371+
environment,
372+
bindType = 'API',
373+
serviceId,
374+
apiId,
375+
endpoint,
376+
usagePlan
377+
}) {
378+
const { usagePlanList } = await this.request({
379+
Action: 'DescribeApiUsagePlan',
380+
serviceId,
381+
apiIds: [apiId]
382+
})
383+
384+
const oldUsagePlan = usagePlanList.find((item) => item.usagePlanId === usagePlan.id)
385+
if (oldUsagePlan) {
386+
console.debug(
387+
`Usage plan with id ${usagePlan.id} already bind to api id ${apiId} path ${endpoint.method} ${endpoint.path}.`
388+
)
389+
} else {
390+
console.debug(
391+
`Binding usage plan with id ${usagePlan.id} to api id ${apiId} path ${endpoint.method} ${endpoint.path}.`
392+
)
393+
await this.request({
394+
Action: 'BindEnvironment',
395+
serviceId,
396+
environment,
397+
bindType: bindType,
398+
usagePlanIds: [usagePlan.id],
399+
apiIds: [apiId]
400+
})
401+
console.debug('Binding successed.')
402+
}
403+
}
404+
341405
async deploy(inputs) {
342-
const { oldState = {} } = inputs
406+
const { environment, oldState = {} } = inputs
343407
inputs.protocols = this.getProtocolString(inputs.protocols)
344408

345409
const { serviceId, serviceName, subDomain, serviceCreated } = await this.createOrUpdateService(
@@ -369,10 +433,51 @@ class Apigw {
369433
curApi.created = true
370434
}
371435

372-
// TODO: set api auth and use plan
373-
// if (endpoint.auth) {
374-
// await this.setupUsagePlan
375-
// }
436+
// set api auth and use plan
437+
if (endpoint.auth) {
438+
curApi.bindType = endpoint.bindType || 'API'
439+
const usagePlan = await this.setupApiUsagePlan({
440+
usagePlan: {
441+
...((exist && exist.usagePlan) || {}),
442+
...endpoint.usagePlan
443+
}
444+
})
445+
// store in api list
446+
curApi.usagePlan = usagePlan
447+
448+
const { secretIds = [] } = endpoint.auth
449+
const secrets = await this.setupUsagePlanSecret({
450+
secretName: endpoint.auth.secretName,
451+
secretIds
452+
})
453+
const unboundSecretIds = await this.getUnboundSecretIds({
454+
usagePlanId: usagePlan.id,
455+
secretIds: secrets.secretIds
456+
})
457+
if (unboundSecretIds.length > 0) {
458+
console.debug(
459+
`Binding secret key ${unboundSecretIds} to usage plan with id ${usagePlan.id}.`
460+
)
461+
await this.request({
462+
Action: 'BindSecretIds',
463+
usagePlanId: usagePlan.id,
464+
secretIds: unboundSecretIds
465+
})
466+
console.debug('Binding secret key successed.')
467+
}
468+
// store in api list
469+
curApi.usagePlan.secrets = secrets
470+
471+
// bind environment
472+
await this.bindUsagePlanEnvironment({
473+
environment,
474+
serviceId,
475+
apiId: curApi.apiId,
476+
bindType: curApi.bindType,
477+
usagePlan,
478+
endpoint
479+
})
480+
}
376481

377482
apiList.push(curApi)
378483
console.debug(
@@ -413,11 +518,63 @@ class Apigw {
413518

414519
async remove(inputs) {
415520
const { created, environment, serviceId, apiList, customDomains } = inputs
416-
// remove all apis
521+
// 1. remove all apis
417522
for (let i = 0; i < apiList.length; i++) {
418523
const curApi = apiList[i]
419-
// TODO: remove usagePlan and api auth(secretIds)
420-
// delete only apis created by serverless framework
524+
525+
// 1. remove usage plan
526+
if (curApi.usagePlan) {
527+
// 1.1 unbind secrete ids
528+
const { secrets } = curApi.usagePlan
529+
if (secrets && secrets.secretIds) {
530+
await this.request({
531+
Action: 'UnBindSecretIds',
532+
secretIds: secrets.secretIds,
533+
usagePlanId: curApi.usagePlan.id
534+
})
535+
console.debug(`Unbinding secret key to usage plan with ID ${curApi.usagePlan.id}.`)
536+
537+
// delelet all created api key
538+
if (curApi.usagePlan.secrets.created === true) {
539+
for (let sIdx = 0; sIdx < secrets.secretIds.length; sIdx++) {
540+
const secretId = secrets.secretIds[sIdx]
541+
await this.request({
542+
Action: 'DisableApiKey',
543+
secretId
544+
})
545+
await this.request({
546+
Action: 'DeleteApiKey',
547+
secretId
548+
})
549+
console.debug(`Removing any previously deployed secret key. ${secretId}`)
550+
}
551+
}
552+
}
553+
554+
// 1.2 unbind environment
555+
await this.request({
556+
Action: 'UnBindEnvironment',
557+
serviceId,
558+
usagePlanIds: [curApi.usagePlan.id],
559+
environment,
560+
bindType: curApi.bindType,
561+
apiIds: [curApi.apiId]
562+
})
563+
console.debug(
564+
`Unbinding usage plan with ID ${curApi.usagePlan.id} to service with ID ${serviceId}.`
565+
)
566+
567+
// 1.3 delete created usage plan
568+
if (curApi.usagePlan.created === true) {
569+
console.debug(`Removing any previously deployed usage plan ids ${curApi.usagePlan.id}`)
570+
await this.request({
571+
Action: 'DeleteUsagePlan',
572+
usagePlanId: curApi.usagePlan.id
573+
})
574+
}
575+
}
576+
577+
// 2. delete only apis created by serverless framework
421578
if (curApi.apiId && curApi.created === true) {
422579
console.debug(`Removing api: ${curApi.apiId}`)
423580
await this.request({
@@ -427,7 +584,8 @@ class Apigw {
427584
})
428585
}
429586
}
430-
// unbind all custom domains
587+
588+
// 2. unbind all custom domains
431589
if (customDomains) {
432590
for (let i = 0; i < customDomains.length; i++) {
433591
const curDomain = customDomains[i]
@@ -442,7 +600,7 @@ class Apigw {
442600
}
443601
}
444602

445-
// unrelease service
603+
// 3. unrelease service
446604
console.debug(`Unreleasing service: ${serviceId}, environment: ${environment}`)
447605
await this.request({
448606
Action: 'UnReleaseService',

src/baas/apigw/index.test.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ async function runTest() {
88

99
const inputs = {
1010
region: 'ap-guangzhou',
11-
serviceId: 'service-dy3d9qlq',
11+
serviceId: 'service-7i9kk5a8',
1212
protocols: ['http', 'https'],
1313
serviceName: 'serverless',
1414
environment: 'release',
1515
customDomains: [
1616
{
1717
domain: 'fullstack.yugasun.com',
18+
// TODO: change to your certId
1819
certificateId: '123456',
1920
isDefaultMapping: 'FALSE',
2021
pathMappingSet: [
@@ -28,19 +29,30 @@ async function runTest() {
2829
],
2930
endpoints: [
3031
{
32+
apiId: 'api-a05zvycu',
3133
path: '/',
3234
protocol: 'HTTP',
3335
method: 'GET',
3436
apiName: 'index',
3537
function: {
3638
functionName: 'egg-function'
39+
},
40+
usagePlan: {
41+
usagePlanName: 'slscmp',
42+
usagePlanDesc: 'sls create',
43+
maxRequestNum: 1000,
44+
},
45+
auth: {
46+
serviceTimeout: 15,
47+
secretName: 'secret',
3748
}
49+
3850
}
3951
]
4052
}
4153
const apigw = new Apigw(credentials, inputs.region)
4254
const outputs = await apigw.deploy(inputs)
43-
console.log('outputs', outputs);
55+
console.log('outputs', JSON.stringify(outputs));
4456

4557

4658
await apigw.remove(outputs)

0 commit comments

Comments
 (0)