GithubHelp home page GithubHelp logo

onxmaps / cypress-iap Goto Github PK

View Code? Open in Web Editor NEW
6.0 33.0 2.0 1.23 MB

This Cypress plugin overwrites the cy.visit command and builds authentication capability google-auth-library to access applications behind Identity Aware Proxy(IAP).

JavaScript 100.00%
cypress identity-aware-proxy google-authentication iap iap-verification

cypress-iap's Introduction

Cypress-IAP npm version cypress-iap status

This Cypress plugin overwrites the cy.visit command and builds authentication capability google-auth-library to access applications behind Identity Aware Proxy(IAP). If the the cypress baseUrl is localhost, the original cy.visit function is returned.

Installation

Install the package using npm:

npm i -D cypress-iap

And add the following at the beginning of your setup file at cypress/support/index.js:

import 'cypress-iap/visit';

Register the plugin

Register the plugin in your cypress/plugins/index.js file like this:

module.exports = (on, config) => {
    require('cypress-iap/utils')(on, config);

    return config;
};

Google Service Account

A google service account should be created within your google cloud project. Upon creation, store the keyfile that is auto generated.

Create a google service account

Do NOT check this file in to your remote repository. Store it outside of your project or .gitignore / .dockerignore your keyfile.

Example google cloud service account

keyfile.json

{
  "type": "service_account",
  "project_id": "<project_id>",
  "private_key_id": "<private_key_id",
  "private_key": "-----BEGIN PRIVATE KEY-----\n <private_key> \n-----END PRIVATE KEY-----\n",
  "client_email": "<service_account_name>@<google_cloud_project>.iam.gserviceaccount.com",
  "client_id": "<client_id>",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/<google_clould_project>.iam.gserviceaccount.com"
}

Set GOOGLE_APPLICATION_CREDENTIALS env variable

Ensure the GOOGLE_APPLICATION_CREDENTIALS environment variable is set to the credentials path of the credentials file.

export GOOGLE_APPLICATION_CREDENTIALS=path/to/keyfile.json

Alternatively you can use third party plugin called as-a and in your as-a.ini you can set the following configuration:

as-a.ini

[auth-me]
GOOGLE_APPLICATION_CREDENTIALS=keyfile.json

This command will execute the as-a package set the variables defined under [auth-me].

as-a auth-me cypress run

cypress-iap's People

Contributors

coltdorsey avatar dependabot[bot] avatar kirkchambers-onx avatar renovate-bot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cypress-iap's Issues

Performance issue with duplicated intercepts from multiple cy.visit calls in test

Thanks so much for this project, it helped me immensely.

I was noticing some severe performance issues on Github actions leading to failed tests, which were not reproducible on my local machine. Those runners which have limited CPU/memory resources, so that gave me a clue that it could be a leak.

As it turns out every cy.visit call was adding a new intercept alias, and Cypress doesn't simply rewrite the old one. Instead, it duplicates the intercept and subsequently processes each intercept for every request. This causes a memory leak and over time each successive request gets slower and slower and results in timeouts.

To address this for myself, I added this utility function in my support commands:

export const iapAuthenticate = () => {
  return cy
    .task("getIAPToken", {
      url: Cypress.config().baseUrl,
    })
    .then(iapToken => {
      if (iapToken) {
        return cy
          .log("IAP detected. Adding auth proxy headers to requests.")
          .intercept(`${Cypress.config().baseUrl}/**`, req => {
            req.headers["Proxy-Authorization"] = `${iapToken}`;
          })
          .as("Cypress-IAP");
      } else {
        return cy.log("No IAP detected");
      }
    });
};

And call it in the beforeEach of each of my test suites, to explicitly ensure that intercepts are only added once.

Note, I also added the client ID resolver to the plugin file so I wouldn't have to cy.exec. Additionally I also persist the iapToken in a plugin variable so it wouldn't duplicate reauthentication:

  // store iapToken for shared use across test run
  var iapToken = null;

  on("task", {
    async getIAPToken({ url }) {
      if (!iapToken && url.indexOf("localhost") == -1) {
        const { exec } = require("child_process");
        const client_id = await new Promise((resolve, reject) => {
          exec(`curl -I ${url} | awk '/^location/ {split($NF, a, /[=&]/); print a[2]}'`, (error, stdout) => {
            if (error) {
              reject(error);
            } else {
              resolve(stdout.trim());
            }
          });
        });
        if (!!client_id) {
          const { GoogleAuth } = require("google-auth-library");
          const auth = new GoogleAuth();
          const client = await auth.getIdTokenClient(client_id.trim());
          const res = await client.request({ url });
          iapToken = res.config.headers.Authorization;
        }
      }
      return iapToken;
    },
  });

Does not work on Windows

On windows, the execution of awk command is causing an issue.
This is what I get while executing on a windows machine :-
Stderr:
[15:38:46][Step 3/4] awk: '/location/
[15:38:46][Step 3/4] awk: ^ invalid char ''' in expression

Looks like issue with single quotes not been recognized in windows cmd

Can we fix this? It would be super useful for us
Thanks in advance

Stopped working, cid is always empty.

I haven't made any changes to my project. When cypress-iap makes a request the cid parameter is now always empty. Anyone else having this problem?

Screenshot 2023-09-22 at 15 09 26

Cypress hangs for me at a specific point when using this plugin for IAP

Hi @coltdorsey ,
Hope you are doing good!
With this new version of IAP published last month I am facing an issue
Cypress would hang for me at a particular point. When I try inspecting my networks tab, I can see there is one XHR which remains in pending state forever when this issue occurs..
I have tried hell lot of options but no luck...I 99% think that the issue is related to IAP hence raising it here..

It used to work fine with the older version of IAP package. It currently works fine against an environment which is not under IAP..
But on executing on an environment under IAP it hangs for me..

I know you must be super busy but will it be possible to get on a call sometime this week and I can share my screen and show?

Thanks,
Nishant Shah

Unable to detect a Project Id in the current environment.

I get the following error and I'm unsure why:
Unable to detect a Project Id in the current environment.

cypress/support/e2e.ts:

import 'cypress-iap/visit';

cypress.config.ts:

export default defineConfig({
  e2e: {
    async setupNodeEvents(on, config) {
      // eslint-disable-next-line @typescript-eslint/no-var-requires
      require('cypress-iap/utils')(on, config);
      const version = config.env.version || 'development'
      const configFile = await import(path.join(
        config.projectRoot,
        'cypress/config',
        `${version}.json`
      ));
      const credentialsFile = await import(path.join(
        config.projectRoot,
        'cypress/config',
        'credentials.json'
      ));
      config = cypressBrowserPermissionsPlugin(on, config)
      config.env =  {
        'browserPermissions': {
          'geolocation': 'allow',
        },
       'GOOGLE_APPLICATION_CREDENTIALS': 'cypress/plugins/serviceAccountKeyDev.json'
      }
      config = {
        ...config,                    // take config defined in this file
        ...configFile                 // merge/override from the external file
      }
      config.env = {
        ...config.env,                // 2nd level merge
        ...credentialsFile[version]   // from git-ignored file 
      }
      config.projectId = "5jgpns"
      config.baseUrl = config.baseUrl || configFile.env.baseUrl
      return config
    },
    reporter: 'mochawesome'
  },
});

Allow specifying domains skipping authentication

We have a different local domain (other than localhost) used for locally-running UI.
It'd be nice if we could specify which domains should skip injecting the Authorization header.

I sadly don't know cypress yet to be able to contribute this myself (yet).

Plugin does not work anymore for me

Hello,
This plugin was working fine until last week, but looks like its not working anymore and I am unable to perform IAP login with it in my cypress tests.
Looks like Google has dropped the logic of performing IAP login via the cookie :- GCP_IAAP_AUTH_TOKEN
Someone from google recently updated this blog :- https://cloud.google.com/blog/products/identity-security/getting-started-with-cloud-identity-aware-proxy and removed this cookie name as well.

@coltdorsey does it still work for you?
If not then are you planning to update this plugin to make it work again?

Thanks,
Nishant Shah

Doesn't work, I still see Google Authentication screen.

I have registered the plugin in cypress/plugins/index.ts like this:

module.exports = async (on, config) => {
    require('cypress-iap/utils')(on, config);
    return config
 }

I have imported it in cypress/support/index.ts like this:
import 'cypress-iap/visit';

The service account is setup and the I have a .env file with the following:
GOOGLE_APPLICATION_CREDENTIALS=cypress/plugins/serviceAccountKeyDev.json

So why isn't it working?

Dependency Dashboard

This issue provides visibility into Renovate updates and their statuses. Learn more

Other Branches

These updates are pending. To force PRs open, click the checkbox below.

  • Update dependency validator to 13.7.0 [SECURITY]

  • Check this box to trigger a request for Renovate to run again on this repository

Wrong injected header key (should be `Authorization`)

Hi, first off, thanks for creating this project, it's exactly what we're trying to get around for testing in our IAP-walled staging environment.

Anyhow, I had to futz with the code a bit to get it working. I changed the injected header to:

req.headers["Authorization"] = `${iapToken}`;

and it seemed to get it working. Let me know if you want me to issue a PR

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.