[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/armonge/serverless-basic-authentication/develop/index.js [Back]  [Original]

const fs = require('fs');
const chalk = require('chalk');
const path = require('path');

module.exports = class SetupBasicAuthentication {
  constructor(serverless, options) {
    this.options = options;
    this.serverless = serverless;

    // add the basic authentication function to the functions as soon as possible
    this.injectBasicAuthFunction(serverless);

    this.hooks = {
      'before:package:initialize': this.addAuthorizer.bind(this),
      'after:package:createDeploymentArtifacts': this.removeAuthorizer.bind(this),
      'before:deploy:deploy': this.configureApiGatewayKeySource.bind(this),
    };
  }

  addAuthorizer() {
    // add our custom authenticator
    this.addAuthFileToPackage();

    this.addAuthorizerFunctionToPrivateFunctions();
  }

  removeAuthorizer() {
    this.serverless.cli.consoleLog(`Basic Authentication: ${chalk.yellow('Removing Symlink for Basic Authenticator')}`);
    fs.unlinkSync(path.normalize(`${this.serverless.config.servicePath}/basic_auth.py`));
  }

  addAuthFileToPackage() {
    if (!this.serverless.package) {
      this.serverless.package = {};
    }

    if (!this.serverless.package.include) {
      this.serverless.package.include = [];
    }

    this.serverless.cli.consoleLog(`Basic Authentication: ${chalk.yellow('Adding Symlink for Basic Authenticator')}`);
    // @TODO: Make target filename randomized with something, to prevent overriding
    // any files

    // append our basic_auth.py file to the package
    this.serverless.package.include.push(path.normalize(`${__dirname}/basic_auth.py`));
    try {
      fs.symlinkSync(path.normalize(`${__dirname}/basic_auth.py`), path.normalize(`${this.serverless.config.servicePath}/basic_auth.py`));
    } catch(error) {
      if(error.errno == -4048 && error.code == 'EPERM'){
        fs.copyFileSync(path.normalize(`${__dirname}/basic_auth.py`),path.normalize(`${this.serverless.config.servicePath}/basic_auth.py`));
      }else{
        throw error;
      }
    }
  }

  injectBasicAuthFunction() {
    this.serverless.cli.consoleLog(`Basic Authentication: ${chalk.yellow('Adding function for Basic Authenticator')}`);
    const basicAuthenticator = {
      handler: 'basic_auth.basicAuth',
      runtime: 'python3.6',
    };

    // add the basic authenticator function
    this.serverless.service.functions.basicAuthenticator = basicAuthenticator;
  }

  addAuthorizerFunctionToPrivateFunctions() {
    // for each function which is marked as 'private', set the basic authenticator
    // if it doesn't have a custom authenticator yet
    Object.keys(this.serverless.service.functions).forEach((functionName) => {
      // ignore our own function
      if (functionName === 'basicAuthenticator') {
        return;
      }

      // get all function configs
      const fnctn = this.serverless.service.functions[functionName];

      // check if any of the http events is marked as private, and if that event
      // also doesn't have a custom authorizer already, apply our authenticator
      Object.keys(fnctn.events).forEach((fnctnEvent) => {
        // if http doesn't exist, skip
        if (!('http' in this.serverless.service.functions[functionName].events[fnctnEvent])) {
          return;
        }

        if (
          this.serverless.service.functions[functionName].events[fnctnEvent].http != null
          && this.serverless.service.functions[functionName].events[fnctnEvent].http.private === true
          && this.serverless.service.functions[functionName].events[fnctnEvent].http.authorizer == null
        ) {
          this.serverless.service.functions[functionName].events[fnctnEvent].http.authorizer = {
            name: 'basicAuthenticator',
            identitySource: '', // this is only valid if we set cache ttl to 0
            resultTtlInSeconds: 0,
            type: 'REQUEST',
          };
          this.serverless.cli.consoleLog(`Basic Authentication: ${chalk.yellow(`Enabled for ${functionName}`)}`);
        }
      });
    });
  }

  configureApiGatewayKeySource() {
    const template = this.serverless.service.provider.compiledCloudFormationTemplate;
    if (template.Resources.ApiGatewayRestApi != null) {
      this.serverless.cli.consoleLog(
        `Basic Authentication: ${chalk.yellow('Configuring Api Gateway for Basic Authenticator')}`,
      );
      template.Resources.ApiGatewayRestApi.Properties.ApiKeySourceType = 'AUTHORIZER';
    }
  }
};

Web Proxy Viewer  |  New URL  |  Original Page