Repository: serverless/serverless (JavaScript)
Date: 2017-10-15 14:01:24+00:00
Task type: Feature

Issue:
Hide api key generated by sls from the serverless console output
<!--
1. If you have a question and not a bug/feature request please ask it at http://forum.serverless.com
2. Please check if an issue already exists so there are no duplicates
3. Check out and follow our Guidelines: https://github.com/serverless/serverless/blob/master/CONTRIBUTING.md
4. Fill out the whole template so we have a good overview on the issue
5. Do not remove any section of the template. If something is not applicable leave it empty but leave it in the Issue
6. Please follow the template, otherwise we'll have to ask you to update it
-->

# This is a Feature Proposal

## Description
Serverless allows generating api key with usage plans.
Here is the serverless document which explains the config for this 

https://serverless.com/framework/docs/providers/aws/events/apigateway/#setting-api-keys-for-your-rest-api


The api key generated gets printed in the console output as mentioned in the link above, which is not a great practice for prod.
So if serverless is running in a common CD tool, someone with readonly access can get the api token by just looking at logs. 
So will be great if serverless can have some option / flag to hide api key generated.



Issue discussion:
I have started to work on this feature 🎉. The api key names will still be displayed in the output however the values will blank.

```console
$ serverless deploy --obfuscate-api-keys

Service Information
service: helloworld
stage: production
region: us-west-1
api keys:
  production-helloworld-user1-key
endpoints:
  POST - https://example.com/say
functions:
  say: helloworld
```

Any thoughts on this proposal? Flag name suggestions are also welcomed 😊 
hi, may be some flag in server config file will be great than adding flag in deploy command as this is a small feature. thoughts?
That's awesome @timstott 💯  Thank you for moving forward 👍 
Let us know if you need any helps to go ahead!
@shahpawan I didn't consider having this options in the config file. I liked it at first. Then realised this options is only concerned with CLI output. In contrast *serverless.yml* is concerned with our application definition.

@horike37 Thanks for the motivation 🎉 ! I'm torn with the option name. All `deploy` options have one word currently (awesome). I wanted to propose  `--conceal-api-keys` but perhaps it can be more universal; to conceal all secrets/tokens displayed on deploy. Then `--obfuscate` or `--conceal` would be more sensible.

I would however only work on concealing the API key values on the upcoming PR. But the universal option would be available for anyone to use.

```console
# Example with --conceal-api-keys (limited output for conciseness)
serverless deploy --help
Plugin: Deploy
deploy ........................ Deploy a Serverless service
    ...
    --verbose / -v ..................... Show all stack events during deployment
    --force ............................ Forces a deployment to take place
    --function / -f .................... Function name. Deploys a single function (see 'deploy function')
    --conceal-api-key .................. Conceal API keys values in output
```

Any thoughts or comments :bowtie: ?

Solution patch:
diff --git a/docs/providers/aws/cli-reference/deploy.md b/docs/providers/aws/cli-reference/deploy.md
index 90c23eb440e..a7ad350e0f9 100644
--- a/docs/providers/aws/cli-reference/deploy.md
+++ b/docs/providers/aws/cli-reference/deploy.md
@@ -24,6 +24,7 @@ serverless deploy
 - `--package` or `-p` path to a pre-packaged directory and skip packaging step.
 - `--verbose` or `-v` Shows all stack events during deployment, and display any Stack Output.
 - `--function` or `-f` Invoke `deploy function` (see above). Convenience shortcut - cannot be used with `--package`.
+- `--conceal` Hides secrets from the output (e.g. API Gateway key values).
 
 ## Artifacts
 
diff --git a/docs/providers/aws/events/apigateway.md b/docs/providers/aws/events/apigateway.md
index ff68cfbc3cc..122be6ed518 100644
--- a/docs/providers/aws/events/apigateway.md
+++ b/docs/providers/aws/events/apigateway.md
@@ -391,7 +391,7 @@ functions:
           private: true
 ```
 
-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.
+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.
 
diff --git a/lib/plugins/aws/info/display.js b/lib/plugins/aws/info/display.js
index 10cf9a6b372..9ef78ca9f23 100644
--- a/lib/plugins/aws/info/display.js
+++ b/lib/plugins/aws/info/display.js
@@ -19,12 +19,17 @@ module.exports = {
   },
 
   displayApiKeys() {
+    const conceal = this.options.conceal;
     const info = this.gatheredData.info;
     let apiKeysMessage = `${chalk.yellow('api keys:')}`;
 
     if (info.apiKeys && info.apiKeys.length > 0) {
       info.apiKeys.forEach((apiKeyInfo) => {
-        apiKeysMessage += `\n  ${apiKeyInfo.name}: ${apiKeyInfo.value}`;
+        if (conceal) {
+          apiKeysMessage += `\n  ${apiKeyInfo.name}`;
+        } else {
+          apiKeysMessage += `\n  ${apiKeyInfo.name}: ${apiKeyInfo.value}`;
+        }
       });
     } else {
       apiKeysMessage += '\n  None';
diff --git a/lib/plugins/deploy/deploy.js b/lib/plugins/deploy/deploy.js
index 8840a9119ba..7be8078edf9 100644
--- a/lib/plugins/deploy/deploy.js
+++ b/lib/plugins/deploy/deploy.js
@@ -28,6 +28,9 @@ class Deploy {
           'finalize',
         ],
         options: {
+          conceal: {
+            usage: 'Hide secrets from the output (e.g. API Gateway key values)',
+          },
           stage: {
             usage: 'Stage of the service',
             shortcut: 's',


Test patch:
diff --git a/lib/plugins/aws/info/display.test.js b/lib/plugins/aws/info/display.test.js
index 22b955c9e0a..9924ccc2ff2 100644
--- a/lib/plugins/aws/info/display.test.js
+++ b/lib/plugins/aws/info/display.test.js
@@ -74,6 +74,20 @@ describe('#display()', () => {
     expect(missingMessage).to.equal(expectedMessage);
   });
 
+  it('should hide API keys values when `--conceal` is given', () => {
+    awsInfo.options.conceal = true;
+    awsInfo.gatheredData.info.apiKeys = [{ name: 'keyOne', value: '1234' }];
+
+    let expectedMessage = '';
+
+    expectedMessage += `${chalk.yellow('api keys:')}`;
+    expectedMessage += '\n  keyOne';
+
+    const message = awsInfo.displayApiKeys();
+    expect(consoleLogStub.calledOnce).to.equal(true);
+    expect(message).to.equal(expectedMessage);
+  });
+
   it('should display endpoints if given', () => {
     awsInfo.serverless.service.functions = {
       function1: {