在 public GitHub 存储库中使用 AWS 凭证(在 node.js 项目中,使用 Grunt.js 构建)

Using AWS credentials in a public GitHub repo (in a node.js project, built with Grunt.js)

我们有一个 MEAN(nodes.js 后端 + angular 前端),我们在其中使用 Amazon S3 sdk 将文件上传到存储服务。我们有我们的 AWS 凭证,我们需要在代码中使用它们。

我们想在 public 存储库中发布我们的项目,但我们不想共享我们的凭据(顺便说一下,Amazon 会监控 GitHub 并通知披露其凭据的开发人员).我们应该如何调整我们的开发工作流程以获得安全(不公开)和方便的东西?

解决方案包括调整 Gruntfile.js 文件,该文件定义了构建过程中需要完成的工作。根据您用作起点的那个,情况会有所不同(并且可能需要考虑各种用例)。

在我们的例子中,我们使用 angular 全栈 yeoman 生成器 (https://github.com/DaftMonk/generator-angular-fullstack) 生成项目框架。生成器生成的 Gruntfile.js 相当复杂,因此我们不得不编辑几个部分。以下是要点:

1。将参数传递给 Grunt

我们首先需要的是能够调用构建过程并传递参数。参数不应最终出现在存储库中,因此开发人员应在代码库 之外创建脚本 以启动构建过程(或每次手动输入参数...)。 Grunt 提供了使用 grunt.option() 函数访问命令行参数的能力。因此,对 Gruntfile.js 文件的第一个修改是在开头添加以下两行:

module.exports = function (grunt) {
  var amznUserId = grunt.option('AMZN_USER_ID');
  var amznUserPassword = grunt.option('AMZN_USER_PASSWORD');
  ...
}

如果您这样做,然后通过键入调用 grunt:

grunt build --AMZN_USER_ID=myUserId --AMZN_USER_PASSWORD=aSecret
grunt serve --AMZN_USER_ID=myUserId --AMZN_USER_PASSWORD=aSecret

然后您将在脚本变量中获得可用的凭据值。

2。在源文件中添加占位符

AMZN 凭据用于 Angular.JS 组件,通常在控制器中。您需要做的是用变量占位符替换硬编码值,如下所示:

angular.module('demoApp')
  .controller('MainCtrl', function ($scope, $http, socket) {
    $scope.amzn_user_id = '@@AMZN_USER_ID';
    $scope.amzn_user_password = '@@AMZN_USER_PASSWORD';

3。将命令行参数注入占位符

解决方案的最后(也是最棘手的)部分是将传递给 grunt 的 2 个值注入占位符。有不同的 Grunt 插件可用于此目的。我们成功地使用了 grunt-replace 插件。这是我们必须做的:

3.1 安装插件

npm install grunt-replace --save

3.2 配置插件(指定注入应该如何发生,最后详细介绍)

grunt.initConfig({   
replace: {
  dist: {
    options: {
      patterns: [
        {
          match: 'AMZN_USER_ID',
          replacement: amznUserId
        },
        {
          match: 'AMZN_USER_PASSWORD',
          replacement: amznUserPassword
        }
      ]
    },
    files: [
      {
        expand: true,
        flatten: false,
        src: ['.tmp/concat/app/app.js'],
        dest: '.'
      },
      {
        expand: false,
        flatten: false,
        src: ['client/app/main/main.controller.js'],
        dest: '.tmp/app/main/main.controller.js'
      }

    ]
  }
},

3.3。在 grunt buildgrunt serve 工作流程中调用插件

请注意顺序很重要,replace 行必须正好位于该位置。

  grunt.registerTask('serve', function (target) {
    if (target === 'dist') {
      return grunt.task.run(['build', 'env:all', 'env:prod', 'express:prod', 'wait', 'open', 'express-keepalive']);
    }

    if (target === 'debug') {
      return grunt.task.run([
        'clean:server',
        'env:all',
        'injector:stylus',
        'concurrent:server',
        'injector',
        'wiredep',
        'autoprefixer',
        'concurrent:debug'
      ]);
    }

    grunt.task.run([
      'clean:server',
      'env:all',
      'injector:stylus',
      'concurrent:server',
      'injector',
      'wiredep',
      'replace',
      'autoprefixer',
      'express:dev',
      'wait',
      'open',
      'watch'
    ]);
  });

grunt.registerTask('build', [
    'clean:dist',
    'injector:stylus',
    'concurrent:dist',
    'injector',
    'wiredep',
    'useminPrepare',
    'autoprefixer',
    'ngtemplates',
    'concat',
    'replace',
    'ngAnnotate',
    'copy:dist',
    'cdnify',
    'cssmin',
    'uglify',
    'rev',
    'usemin'
  ]);

幕后发生了什么

关键是要意识到 angular 全栈生成器定义了一个构建工作流,其中使用了一个名为 .tmp 的特殊目录。这个目录的内容并不总是相同的(grunt buildgrunt serve 使用它的方式略有不同)。这就是我们必须定义两个替换规则的原因。