Skip to content
Merged
Show file tree
Hide file tree
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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -968,6 +968,8 @@ provider:
- myFirstKey
- ${opt:stage}-myFirstKey
- ${env:MY_API_KEY} # you can hide it in a serverless variable
- name: myKeyWithValue # object form — lets you set a specific key value
value: myApiKeyValue
usagePlan:
quota:
limit: 5000
Expand Down Expand Up @@ -1004,6 +1006,8 @@ functions:
- serverless-step-functions
```

API key entries can be plain strings (the key name) or objects with a `name` and an optional `value` property. When `value` is provided, the API key is created with that specific value; otherwise AWS auto-generates the value.

Please note that those are the API keys names, not the actual values. Once you deploy your service, the value of those API keys will be auto generated by AWS and printed on the screen for you to use. The values can be concealed from the output with the --conceal deploy option.

Clients connecting to this Rest API will then need to set any of these API keys values in the x-api-key header of their request. This is only necessary for functions where the private property is set to true.
Expand Down
29 changes: 19 additions & 10 deletions lib/deploy/events/apiGateway/apiKeys.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,33 @@ module.exports = {
_.forEach(apiKeys, (apiKey, i) => {
const apiKeyNumber = i + 1;

if (typeof apiKey !== 'string') {
throw new this.serverless.classes.Error('API Keys must be strings');
if (typeof apiKey !== 'string' && (typeof apiKey !== 'object' || !apiKey.name)) {
throw new this.serverless.classes.Error('API Keys must be strings or objects with a name property');
}

const apiKeyName = typeof apiKey === 'object' ? apiKey.name : apiKey;
const apiKeyValue = typeof apiKey === 'object' ? apiKey.value : undefined;

const apiKeyLogicalId = this.provider.naming
.getApiKeyLogicalId(apiKeyNumber);

const properties = {
Enabled: true,
Name: apiKeyName,
StageKeys: [{
RestApiId: { Ref: this.apiGatewayRestApiLogicalId },
StageName: this.provider.getStage(),
}],
};

if (apiKeyValue !== undefined) {
properties.Value = apiKeyValue;
}

_.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources, {
[apiKeyLogicalId]: {
Type: 'AWS::ApiGateway::ApiKey',
Properties: {
Enabled: true,
Name: apiKey,
StageKeys: [{
RestApiId: { Ref: this.apiGatewayRestApiLogicalId },
StageName: this.provider.getStage(),
}],
},
Properties: properties,
DependsOn: this.apiGatewayDeploymentLogicalId,
},
});
Expand Down
33 changes: 32 additions & 1 deletion lib/deploy/events/apiGateway/apiKeys.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,39 @@ describe('#methods()', () => {
expect(() => serverlessStepFunctions.compileApiKeys()).to.throw(Error);
});

it('throw error if an apiKey is not a string', () => {
it('throw error if an apiKey is not a string or object', () => {
serverlessStepFunctions.serverless.service.provider.apiGateway.apiKeys = [2];
expect(() => serverlessStepFunctions.compileApiKeys()).to.throw(Error);
});

it('should compile api key resource when apiKey is an object with name and value', () => {
serverlessStepFunctions.serverless.service.provider.apiGateway.apiKeys = [
{ name: 'my-api-key', value: 'my-secret-value' },
];
return serverlessStepFunctions.compileApiKeys().then(() => {
const resource = serverlessStepFunctions.serverless.service.provider
.compiledCloudFormationTemplate.Resources[
serverlessStepFunctions.provider.naming.getApiKeyLogicalId(1)
];
expect(resource.Type).to.equal('AWS::ApiGateway::ApiKey');
expect(resource.Properties.Name).to.equal('my-api-key');
expect(resource.Properties.Value).to.equal('my-secret-value');
expect(resource.Properties.Enabled).to.equal(true);
});
});

it('should compile api key resource when apiKey is an object with name only', () => {
serverlessStepFunctions.serverless.service.provider.apiGateway.apiKeys = [
{ name: 'my-api-key' },
];
return serverlessStepFunctions.compileApiKeys().then(() => {
const resource = serverlessStepFunctions.serverless.service.provider
.compiledCloudFormationTemplate.Resources[
serverlessStepFunctions.provider.naming.getApiKeyLogicalId(1)
];
expect(resource.Type).to.equal('AWS::ApiGateway::ApiKey');
expect(resource.Properties.Name).to.equal('my-api-key');
expect(resource.Properties.Value).to.equal(undefined);
});
});
});
Loading