Skip to content

Commit

Permalink
feat(cert) add certificate generation for macOS WD-4079 #331
Browse files Browse the repository at this point in the history
  • Loading branch information
edlerd committed Jun 7, 2023
1 parent ba93c34 commit 30e6ff6
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 27 deletions.
67 changes: 63 additions & 4 deletions src/pages/certificates/BrowserImport.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
import React, { FC, useState } from "react";
import { Col, Row, Tabs } from "@canonical/react-components";
import {
Button,
Col,
Notification,
Row,
Tabs,
} from "@canonical/react-components";

const FIREFOX = "Firefox";
const CHROME_LINUX = "Chrome (Linux)";
const CHROME_WINDOWS = "Chrome (Windows)";
const EDGE = "Edge";
const TABS: string[] = [FIREFOX, CHROME_LINUX, CHROME_WINDOWS, EDGE];
const MACOS = "macOS";
const TABS: string[] = [FIREFOX, CHROME_LINUX, CHROME_WINDOWS, EDGE, MACOS];

const BrowserImport: FC = () => {
interface Props {
sendPfx?: () => void;
}

const BrowserImport: FC<Props> = ({ sendPfx }) => {
const [activeTab, handleTabChange] = useState(FIREFOX);

const windowsDialogSteps = (
Expand All @@ -27,6 +38,17 @@ const BrowserImport: FC = () => {
</>
);

const downloadPfx = (
<li className="p-list__item u-clearfix">
Download <code>lxd-ui.pfx</code>
{sendPfx && (
<div className="u-float-right--large">
<Button onClick={sendPfx}>Download pfx</Button>
</div>
)}
</li>
);

return (
<Row>
<Col size={8}>
Expand All @@ -41,6 +63,7 @@ const BrowserImport: FC = () => {
{activeTab === FIREFOX && (
<div role="tabpanel" aria-label="firefox">
<ul className="p-list--divided u-no-margin--bottom">
{downloadPfx}
<li className="p-list__item">
Paste this link into the address bar:
<div className="p-code-snippet u-no-margin--bottom">
Expand Down Expand Up @@ -72,6 +95,7 @@ const BrowserImport: FC = () => {
{activeTab === CHROME_LINUX && (
<div role="tabpanel" aria-label="chrome linux">
<ul className="p-list--divided u-no-margin--bottom">
{downloadPfx}
<li className="p-list__item">
Paste into the address bar:
<div className="p-code-snippet u-no-margin--bottom">
Expand All @@ -96,6 +120,7 @@ const BrowserImport: FC = () => {
{activeTab === CHROME_WINDOWS && (
<div role="tabpanel" aria-label="chrome windows">
<ul className="p-list--divided u-no-margin--bottom">
{downloadPfx}
<li className="p-list__item">
Paste into the address bar:
<div className="p-code-snippet u-no-margin--bottom">
Expand All @@ -114,8 +139,9 @@ const BrowserImport: FC = () => {
)}

{activeTab === EDGE && (
<div role="tabpanel" aria-label="chrome windows">
<div role="tabpanel" aria-label="edge windows">
<ul className="p-list--divided u-no-margin--bottom">
{downloadPfx}
<li className="p-list__item">
Paste into the address bar:
<div className="p-code-snippet u-no-margin--bottom">
Expand All @@ -132,6 +158,39 @@ const BrowserImport: FC = () => {
</ul>
</div>
)}

{activeTab === MACOS && (
<div role="tabpanel" aria-label="safari macos">
<ul className="p-list--divided u-no-margin--bottom">
<li className="p-list__item">
<Notification
severity="caution"
className="u-no-margin--bottom"
>
The certificate must be protected by password. An empty
password will fail to be imported on macOS.
</Notification>
</li>
{downloadPfx}
<li className="p-list__item">
Start the Keychain Access app on your Mac, select the login
keychain.
</li>
<li className="p-list__item">
Drag the <code>lxd-ui.pfx</code> file onto the Keychain Access
app.
</li>
<li className="p-list__item">
If you are asked to provide a name and password, type the name
and password for an administrator user on this computer.
</li>
<li className="p-list__item">
Restart the browser and open LXD-UI. Select the LXD-UI
certificate.
</li>
</ul>
</div>
)}
</Col>
</Row>
);
Expand Down
31 changes: 8 additions & 23 deletions src/pages/certificates/CertificateGenerate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,29 +154,14 @@ const CertificateGenerate: FC = () => {
Import
</h2>
</Col>
<Col size={6}>
<div className="p-stepped-list__content">
<p>
Download <code>lxd-ui.pfx</code> and import it into
your browser.
</p>
</div>
</Col>
{certs && (
<Col size={3}>
<Button
onClick={() =>
downloadBase64("lxd-ui.pfx", certs.pfx)
}
>
Download pfx
</Button>
</Col>
)}
</Row>
<Row>
<Col emptyLarge={4} size={8}>
<BrowserImport />
<Col size={8}>
<BrowserImport
sendPfx={
certs
? () => downloadBase64("lxd-ui.pfx", certs.pfx)
: undefined
}
/>
</Col>
</Row>
</li>
Expand Down
1 change: 1 addition & 0 deletions src/pages/certificates/PasswordModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ const PasswordModal: FC<Props> = ({ onConfirm, onClose }) => {
onChange={formik.handleChange}
value={formik.values.password}
error={formik.touched.password ? formik.errors.password : null}
help="For macOS an empty password is not allowed. On other systems this step can be skipped."
/>
<Input
id="passwordConfirm"
Expand Down
1 change: 1 addition & 0 deletions src/util/certificate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export const generateCert = (password: string) => {
const crt = forge.pki.certificateToPem(cert);

const asn1 = forge.pkcs12.toPkcs12Asn1(keys.privateKey, [cert], password, {
algorithm: "3des", // would like to use aes, but macOS keychain only supports 3des
generateLocalKeyId: true,
friendlyName: "LXD-UI",
});
Expand Down

0 comments on commit 30e6ff6

Please sign in to comment.