index.tsx 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import {useMemo} from 'react';
  2. import styled from '@emotion/styled';
  3. import {LinkButton} from 'sentry/components/button';
  4. import {KeyValueTable, KeyValueTableRow} from 'sentry/components/keyValueTable';
  5. import LoadingError from 'sentry/components/loadingError';
  6. import LoadingIndicator from 'sentry/components/loadingIndicator';
  7. import Panel from 'sentry/components/panels/panel';
  8. import PanelBody from 'sentry/components/panels/panelBody';
  9. import PanelHeader from 'sentry/components/panels/panelHeader';
  10. import PanelItem from 'sentry/components/panels/panelItem';
  11. import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
  12. import {t, tct} from 'sentry/locale';
  13. import type {ProjectKey} from 'sentry/types';
  14. import {useApiQuery} from 'sentry/utils/queryClient';
  15. import recreateRoute from 'sentry/utils/recreateRoute';
  16. import routeTitleGen from 'sentry/utils/routeTitle';
  17. import useOrganization from 'sentry/utils/useOrganization';
  18. import {useParams} from 'sentry/utils/useParams';
  19. import {useRoutes} from 'sentry/utils/useRoutes';
  20. import SettingsPageHeader from 'sentry/views/settings/components/settingsPageHeader';
  21. import TextBlock from 'sentry/views/settings/components/text/textBlock';
  22. import ReportUri from 'sentry/views/settings/projectSecurityHeaders/reportUri';
  23. function ProjectSecurityHeaders() {
  24. const organization = useOrganization();
  25. const routes = useRoutes();
  26. const params = useParams();
  27. const {projectId} = useParams();
  28. const {
  29. data: keyList,
  30. isLoading,
  31. isError,
  32. refetch,
  33. } = useApiQuery<ProjectKey[]>([`/projects/${organization.slug}/${projectId}/keys/`], {
  34. staleTime: 0,
  35. });
  36. const reports = useMemo(
  37. () => [
  38. {
  39. name: 'Content Security Policy (CSP)',
  40. url: recreateRoute('csp/', {routes, params}),
  41. },
  42. {
  43. name: 'Certificate Transparency (Expect-CT)',
  44. url: recreateRoute('expect-ct/', {routes, params}),
  45. },
  46. {
  47. name: 'HTTP Public Key Pinning (HPKP)',
  48. url: recreateRoute('hpkp/', {routes, params}),
  49. },
  50. ],
  51. [routes, params]
  52. );
  53. if (isLoading) {
  54. return <LoadingIndicator />;
  55. }
  56. if (isError) {
  57. return <LoadingError onRetry={refetch} />;
  58. }
  59. return (
  60. <div>
  61. <SentryDocumentTitle
  62. title={routeTitleGen(t('Security Headers'), projectId, false)}
  63. />
  64. <SettingsPageHeader title={t('Security Header Reports')} />
  65. <ReportUri keyList={keyList} projectId={projectId} orgId={organization.slug} />
  66. <Panel>
  67. <PanelHeader>{t('Additional Configuration')}</PanelHeader>
  68. <PanelBody withPadding>
  69. <TextBlock style={{marginBottom: 20}}>
  70. {tct(
  71. 'In addition to the [key_param] parameter, you may also pass the following within the querystring for the report URI:',
  72. {
  73. key_param: <code>sentry_key</code>,
  74. }
  75. )}
  76. </TextBlock>
  77. <KeyValueTable>
  78. <KeyValueTableRow
  79. keyName="sentry_environment"
  80. value={t('The environment name (e.g. production).')}
  81. />
  82. <KeyValueTableRow
  83. keyName="sentry_release"
  84. value={t('The version of the application.')}
  85. />
  86. </KeyValueTable>
  87. </PanelBody>
  88. </Panel>
  89. <Panel>
  90. <PanelHeader>{t('Supported Formats')}</PanelHeader>
  91. <PanelBody>
  92. {reports.map(({name, url}) => (
  93. <ReportItem key={url}>
  94. <HeaderName>{name}</HeaderName>
  95. <LinkButton to={url} priority="primary">
  96. {t('Instructions')}
  97. </LinkButton>
  98. </ReportItem>
  99. ))}
  100. </PanelBody>
  101. </Panel>
  102. </div>
  103. );
  104. }
  105. export default ProjectSecurityHeaders;
  106. const ReportItem = styled(PanelItem)`
  107. align-items: center;
  108. justify-content: space-between;
  109. `;
  110. const HeaderName = styled('span')`
  111. font-size: 1.2em;
  112. `;