123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- import {RouteComponentProps} from 'react-router';
- import ExternalLink from 'sentry/components/links/externalLink';
- import {Panel, PanelBody, PanelHeader} from 'sentry/components/panels';
- import PreviewFeature from 'sentry/components/previewFeature';
- import {t, tct} from 'sentry/locale';
- import {ProjectKey} from 'sentry/types';
- import routeTitleGen from 'sentry/utils/routeTitle';
- import AsyncView from 'sentry/views/asyncView';
- import SettingsPageHeader from 'sentry/views/settings/components/settingsPageHeader';
- import ReportUri, {
- getSecurityDsn,
- } from 'sentry/views/settings/projectSecurityHeaders/reportUri';
- type Props = RouteComponentProps<{orgId: string; projectId: string}, {}>;
- type State = {
- keyList: null | ProjectKey[];
- } & AsyncView['state'];
- export default class ProjectHpkpReports extends AsyncView<Props, State> {
- getEndpoints(): ReturnType<AsyncView['getEndpoints']> {
- const {orgId, projectId} = this.props.params;
- return [['keyList', `/projects/${orgId}/${projectId}/keys/`]];
- }
- getTitle() {
- const {projectId} = this.props.params;
- return routeTitleGen(t('HTTP Public Key Pinning (HPKP)'), projectId, false);
- }
- getInstructions(keyList: ProjectKey[]) {
- return (
- 'def middleware(request, response):\n' +
- " response['Public-Key-Pins'] = \\\n" +
- ' \'pin-sha256="cUPcTAZWKaASuYWhhneDttWpY3oBAkE3h2+soZS7sWs="; \' \\\n' +
- ' \'pin-sha256="M8HztCzM3elUxkcjR2S5P4hhyBNf6lHkmjAHKhpGPWE="; \' \\\n' +
- " 'max-age=5184000; includeSubDomains; ' \\\n" +
- ` \'report-uri="${getSecurityDsn(keyList)}"\' \n` +
- ' return response\n'
- );
- }
- getReportOnlyInstructions(keyList: ProjectKey[]) {
- return (
- 'def middleware(request, response):\n' +
- " response['Public-Key-Pins-Report-Only'] = \\\n" +
- ' \'pin-sha256="cUPcTAZWKaASuYWhhneDttWpY3oBAkE3h2+soZS7sWs="; \' \\\n' +
- ' \'pin-sha256="M8HztCzM3elUxkcjR2S5P4hhyBNf6lHkmjAHKhpGPWE="; \' \\\n' +
- " 'max-age=5184000; includeSubDomains; ' \\\n" +
- ` \'report-uri="${getSecurityDsn(keyList)}"\' \n` +
- ' return response\n'
- );
- }
- renderBody() {
- const {params} = this.props;
- const {keyList} = this.state;
- if (!keyList) {
- return null;
- }
- return (
- <div>
- <SettingsPageHeader title={t('HTTP Public Key Pinning')} />
- <PreviewFeature />
- <ReportUri keyList={keyList} orgId={params.orgId} projectId={params.projectId} />
- <Panel>
- <PanelHeader>{t('About')}</PanelHeader>
- <PanelBody withPadding>
- <p>
- {tct(
- `[link:HTTP Public Key Pinning]
- (HPKP) is a security feature that tells a web client to associate a specific
- cryptographic public key with a certain web server to decrease the risk of MITM
- attacks with forged certificates. It's enforced by browser vendors, and Sentry
- supports capturing violations using the standard reporting hooks.`,
- {
- link: (
- <ExternalLink href="https://en.wikipedia.org/wiki/HTTP_Public_Key_Pinning" />
- ),
- }
- )}
- </p>
- <p>
- {t(
- `To configure HPKP reports
- in Sentry, you'll need to send a header from your server describing your
- policy, as well specifying the authenticated Sentry endpoint.`
- )}
- </p>
- <p>
- {t(
- 'For example, in Python you might achieve this via a simple web middleware'
- )}
- </p>
- <pre>{this.getInstructions(keyList)}</pre>
- <p>
- {t(`Alternatively you can setup HPKP reports to simply send reports rather than
- actually enforcing the policy`)}
- </p>
- <pre>{this.getReportOnlyInstructions(keyList)}</pre>
- <p>
- {tct(
- `We recommend setting this up to only run on a percentage of requests, as
- otherwise you may find that you've quickly exhausted your quota. For more
- information, take a look at [link:the documentation on MDN].`,
- {
- link: (
- <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Public_Key_Pinning" />
- ),
- }
- )}
- </p>
- </PanelBody>
- </Panel>
- </div>
- );
- }
- }
|