nightwatch测试
My team has recently started implementing CSP on our website. As we started building out the configuration we realised that we were manually testing things and our feedback loop was not as small as we would have liked. We decided to create some tests so we wouldn’t have to retest all the different pages after changing things.
我的团队最近开始在我们的网站上实施CSP。 当我们开始构建配置时,我们意识到我们正在手动测试事物,并且我们的反馈循环并不像我们想要的那么小。 我们决定创建一些测试,以便在进行更改后不必重新测试所有不同的页面。
This story walks through some of the key parts of how we tested our CSP header using an example application which can be found here.
该故事介绍了如何使用示例应用程序测试CSP标头的一些关键部分,该示例应用程序可在此处找到。
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/8965e90d0c500fbe473a6ad416bf8099.png)
内容安全政策标题 (Content Security Policy Headers)
Content security policy (CSP) headers allow pages to specify where external resources can be loaded in from. The main goal of this header is to mitigate XSS attacks. The header is made up of a number of “directives” which give you granular control of the various types of resources that pages may load in, such as image, CSS, and javascript. Mozilla has some great documentation on the header here.
内容安全策略(CSP)标头允许页面指定可以从何处加载外部资源。 此标头的主要目标是减轻XSS攻击。 标头由许多“指令”组成,这些“指令”使您可以精确控制页面可能加载的各种资源类型,例如图像,CSS和javascript。 Mozilla在此处的标头上有一些很棒的文档。
There are actually two CSP headers, Content-Security-Policy
and Content-Security-Policy-Report-Only
. The reporting header does not enforce the policy and block resources, rather it allows you to gather information on the resources which will be blocked. One of the options in both headers is to provide a report URL. When a violation occurs (or would occur if the reporting header is in use) a JSON payload is sent to the reporting URL containing information on what has been blocked. For the rest of this article, it does not matter which header is in use as it will work the same.
实际上有两个CSP标头, Content-Security-Policy
和Content-Security-Policy-Report-Only
。 报告标头不执行策略并阻止资源,而是允许您收集有关将被阻止的资源的信息。 两个标题中的一个选项是提供报告URL。 发生违规时(或者如果正在使用报告标头,则可能会发生违规),会将JSON有效负载发送到报告URL,其中包含有关已阻止内容的信息。 对于本文的其余部分,使用哪个标头并不重要,因为它的工作原理相同。
If the CSP header is incorrectly configured it could cause large amounts of functionality to stop working. CSP has the ability to stop resources such as JavaScript and CSS to be loaded in. This could make your website completely unreadable in the case of CSS or make interactive features unresponsive if JavaScript is blocked.
如果CSP标头配置不正确,则可能导致大量功能停止工作。 CSP能够停止加载诸如JavaScript和CSS之类的资源。如果使用CSS,这可能会使您的网站完全不可读,或者如果JavaScript被阻止,则使交互式功能无法响应。
Even if reporting only is enabled, if CSP is misconfigured it could cause a huge amount of traffic to be sent to the reporting endpoint. Depending on where this endpoint is hosted it could take down your website if it could not handle the load and/or cost a large amount of money in terms of reporting data storage.
即使仅报告功能已启用,如果CSP配置错误,也可能导致将大量流量发送到报告端点。 根据该端点的托管位置,如果它无法处理负载和/或在报告数据存储方面花费大量金钱,则可能会关闭您的网站。
夜间值班 (Nightwatch)
Nightwatch is a testing framework that can use real browsers to test websites. For testing CSP this allows us to see how the browser will behave with our header. Nightwatch can be used against a live or pre-prod environment. In our case, we’re going to spin up our application locally. This allows us to run our tests before deploying or event committing to version control.
Nightwatch是一个测试框架,可以使用真正的浏览器来测试网站。 为了测试CSP,这使我们能够了解浏览器在标题下的行为。 夜视仪可用于现场或预生产环境。 就我们而言,我们将在本地启动我们的应用程序。 这使我们能够在部署或事件提交到版本控制之前运行测试。
For more information on Nightwatch check out their getting started guide.
有关Nightwatch的更多信息,请查看其入门指南 。
测试中 (Testing)
The below excerpt shows how our CSP tests are set up. The test is spinning up our whole application so we can run tests against it. At the top, we require in http
so we can start a server and then we require in our actual app. Nightwatch provides us with some handy hooks in its lifecycle. The before hook runs once before all tests, here we start up a server for our application. Next, we register an after hook to shut down the server once all the tests have completed.
以下摘录显示了如何设置我们的CSP测试。 该测试正在使整个应用程序扩展,因此我们可以对其进行测试。 在顶部,我们要求使用http
以便我们可以启动服务器,然后在实际应用中要求。 Nightwatch在生命周期中为我们提供了一些方便的方法。 before挂钩在所有测试之前运行一次,这里我们为应用程序启动服务器。 接下来,我们注册了一个After钩子,以在所有测试完成后关闭服务器。
Testing for violations can be done by checking the logs returned by the browser. In the example below, we open the root page of the application, wait for the body to be visible then check to see if there are any logs. We filter the returned logs so if the page does have other logs they do not give us false negatives. If any security logs are found an exception is thrown which causes the test to fail.
可以通过检查浏览器返回的日志来进行违规测试。 在下面的示例中,我们打开应用程序的根页面,等待正文可见,然后检查是否有任何日志。 我们过滤返回的日志,因此,如果该页面上还有其他日志,它们不会给我们带来负面的负面影响。 如果发现任何安全日志,则会引发异常,从而导致测试失败。
Getting the logs from the browser is only supported by Chrome. Nightwatch allows you to configure different environments that can use different browsers. In the package.json
file, we have enabled the chrome environment when running these tests by setting the argument -e chrome
.
Chrome仅支持从浏览器获取日志。 Nightwatch允许您配置可以使用不同浏览器的不同环境。 在package.json
文件中,我们通过设置参数-e chrome
在运行这些测试时启用了chrome环境。
The full test can be found here.
完整的测试可以在 这里 找到 。
So far we have tested that our application still works with our new CSP header but we haven't tested whether the CSP is actually blocking resources. As we don’t want to introduce pages into our application that are just for testing we create a test-specific application. This application needs to reuse the same CSP configuration, so in the example project we have extracted this out into its own module. This module can then be reused in the test application as shown below.
到目前为止,我们已经测试过我们的应用程序仍然可以与新的CSP标头一起使用,但是我们还没有测试过CSP是否实际上在阻塞资源。 因为我们不想在应用程序中引入仅用于测试的页面,所以我们创建了特定于测试的应用程序。 该应用程序需要重用相同的CSP配置,因此在示例项目中,我们已将其提取到其自己的模块中 。 然后可以在测试应用程序中重用此模块,如下所示。
The below file is a snippet from the top of a Nightwatch test and shows how we can create a test application just for the test. This test is now requiring in express
and creating a new express application. Then we register a piece of middleware that will serve static content so we can serve test HTML pages. These pages can include resources that we want to check are blocked. The test is similar to the example above however rather than throwing an exception when logs are found, an exception is thrown if no logs are found.
下面的文件是Nightwatch测试顶部的摘录,显示了我们如何为该测试创建测试应用程序。 现在,此测试需要express
并创建一个新的快速表达应用程序。 然后,我们注册一个将提供静态内容的中间件,以便我们可以提供测试HTML页面。 这些页面可能包含我们要检查的资源被阻止。 测试类似于上面的示例,但是不是在找到日志时抛出异常,而是在未找到日志时抛出异常。
The full test can be found here.
完整的测试可以在 这里 找到 。
测试策略 (Testing Strategy)
We are going to cover a few scenarios on what you may want to test when implementing CSP. First, we will look at a simple app that is self-contained, then we’ll look at how we can test when using micro frontends, and finally we will look at testing CSP blocking resources.
我们将介绍一些实施CSP时可能要测试的方案。 首先,我们将看一个自包含的简单应用程序,然后看如何在使用微前端时进行测试,最后看一下测试CSP阻塞资源。
In a simple self-contained application, you should have some browser tests already set up. When running these tests an extra assertion as above can be added in to check that there have not been any CSP violations. This gives you confidence that the application still works functionally with CSP enabled and also checks that there are no scripts being blocked in the background.
在一个简单的独立应用程序中,您应该已经设置了一些浏览器测试。 运行这些测试时,可以添加上述额外的声明,以检查是否没有任何CSP违规行为。 这使您确信该应用程序仍可在启用CSP的情况下正常运行,并且还可以检查是否在后台阻止了任何脚本。
When working with micro front ends a gateway may be responsible for setting the header. In this scenario, you don’t have any real pages to test, however you still want to test your header. In this case, we can create some tests similar to the violation tests above. We can create basic HTML files with known examples of resources being loaded in and run them through the Nightwatch tests. This gives us confidence that if we change the CSP header we don’t regress and new rules are being applied. Owners of the page services should also run browser tests as if they were a self-contained application and check for CSP violations. They can then feedback to the gateway team to change the header. Or, even better, the gateway could have a way for specific pages to override the CSP.
使用微型前端时,网关可能负责设置标头。 在这种情况下,您没有要测试的实际页面,但是您仍然想测试标题。 在这种情况下,我们可以创建一些类似于上述违规测试的测试。 我们可以使用已加载资源的已知示例创建基本HTML文件,并通过Nightwatch测试运行它们。 这使我们充满信心,如果我们更改CSP标头,则不会退步,并且会应用新规则。 页面服务的所有者还应该像自己运行的应用程序一样运行浏览器测试,并检查是否违反CSP。 然后,他们可以反馈给网关团队以更改标题。 或者,甚至更好的是,网关可以为特定页面覆盖CSP。
It’s important that our website still works when enabling CSP. However, if CSP is not working there’s not much point in having the header. We should also create some pages with resources that violate the CSP, confirming that if someone managed to inject something malicious it would be caught. In the example project and tests, we just check that there’s a log output into the console but this could be taken a step further by creating a mock report URL and checking the data posted to it.
启用CSP时,我们的网站仍然可以正常工作很重要。 但是,如果CSP无法正常工作,那么拥有标头就没有多大意义。 我们还应该使用违反CSP的资源来创建一些页面,确认如果有人设法注入恶意内容,则会被捕获。 在示例项目和测试中,我们只检查控制台中是否有日志输出,但是可以通过创建模拟报告URL并检查发布到其上的数据来采取进一步的措施。
CSP headers are a complicated beast and have the ability to cripple a website. By writing tests as shown in this article you should be able to release with the confidence that your website and CSP are working as required. For a full example check out this project.
CSP标头是一个复杂的野兽,具有削弱网站的能力。 通过编写本文中所示的测试,您应该可以放心地释放您的网站和CSP的要求。 有关完整示例,请查看此项目 。
nightwatch测试