static assets should not use csrf (Set-Cookie) (#23357)

* static assets should not use csrf (Set-Cookie)

Part of #1316

* move setFastlySurrogateKey up too
This commit is contained in:
Peter Bengtsson 2021-12-06 08:00:34 -05:00 коммит произвёл GitHub
Родитель b91d720f73
Коммит 7c66d4456f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 50 добавлений и 28 удалений

Просмотреть файл

@ -81,6 +81,39 @@ export default function (app) {
app.use(datadog)
}
// Must appear before static assets and all other requests
// otherwise we won't be able to benefit from that functionality
// for static assets as well.
app.use(setFastlySurrogateKey)
// Must come before `csrf` otherwise you get a Set-Cookie on successful
// asset requests. And it can come before `rateLimit` because if it's a
// 200 OK, the rate limiting won't matter anyway.
// archivedEnterpriseVersionsAssets must come before static/assets
app.use(
asyncMiddleware(
instrument(archivedEnterpriseVersionsAssets, './archived-enterprise-versions-assets')
)
)
app.use(
'/assets',
express.static('assets', {
index: false,
etag: false,
lastModified: false,
maxAge: '1 day', // Relatively short in case we update images
})
)
app.use(
'/public',
express.static('data/graphql', {
index: false,
etag: false,
lastModified: false,
maxAge: '7 days', // A bit longer since releases are more sparse
})
)
// *** Early exits ***
// Don't use the proxy's IP, use the requester's for rate limiting
// See https://expressjs.com/en/guide/behind-proxies.html
@ -110,7 +143,6 @@ export default function (app) {
app.set('etag', false) // We will manage our own ETags if desired
app.use(compression())
app.use(disableCachingOnSafari)
app.use(setFastlySurrogateKey)
app.use(catchBadAcceptLanguage)
// *** Config and context for redirects ***
@ -136,31 +168,6 @@ export default function (app) {
app.use(haltOnDroppedConnection)
// *** Rendering, 2xx responses ***
// I largely ordered these by use frequency
// archivedEnterpriseVersionsAssets must come before static/assets
app.use(
asyncMiddleware(
instrument(archivedEnterpriseVersionsAssets, './archived-enterprise-versions-assets')
)
)
app.use(
'/assets',
express.static('assets', {
index: false,
etag: false,
lastModified: false,
maxAge: '1 day', // Relatively short in case we update images
})
)
app.use(
'/public',
express.static('data/graphql', {
index: false,
etag: false,
lastModified: false,
maxAge: '7 days', // A bit longer since releases are more sparse
})
)
app.use('/events', asyncMiddleware(instrument(events, './events')))
app.use('/search', asyncMiddleware(instrument(search, './search')))

Просмотреть файл

@ -956,11 +956,26 @@ describe('?json query param for context debugging', () => {
describe('static routes', () => {
it('serves content from the /assets directory', async () => {
expect((await get('/assets/images/site/be-social.gif')).statusCode).toBe(200)
const res = await get('/assets/images/site/be-social.gif')
expect(res.statusCode).toBe(200)
expect(res.headers['cache-control']).toContain('public')
expect(res.headers['cache-control']).toMatch(/max-age=\d+/)
// Because static assets shouldn't use CSRF and thus shouldn't
// be setting a cookie.
expect(res.headers['set-cookie']).toBeUndefined()
// The "Surrogate-Key" header is set so we can do smart invalidation
// in the Fastly CDN. This needs to be available for static assets too.
expect(res.headers['surrogate-key']).toBeTruthy()
})
it('serves schema files from the /data/graphql directory at /public', async () => {
expect((await get('/public/schema.docs.graphql')).statusCode).toBe(200)
const res = await get('/public/schema.docs.graphql')
expect(res.statusCode).toBe(200)
expect(res.headers['cache-control']).toContain('public')
expect(res.headers['cache-control']).toMatch(/max-age=\d+/)
// Because static assets shouldn't use CSRF and thus shouldn't
// be setting a cookie.
expect(res.headers['set-cookie']).toBeUndefined()
expect(
(await get(`/public/ghes-${enterpriseServerReleases.latest}/schema.docs-enterprise.graphql`))
.statusCode