wip: completed the content, move on to post cover etc

This commit is contained in:
Suyono 2024-05-24 21:16:36 +10:00
parent 7252456dd4
commit 0d09e0d44f
4 changed files with 241 additions and 25 deletions

1
.env
View File

@ -1 +1,2 @@
DUMMY_HTML_DIR=./development-test-data-dir/
ASSETS_DOMAIN=assets.suyono.me

View File

@ -2,7 +2,7 @@ import { unified } from 'unified';
import remarkGfm from 'remark-gfm';
import remarkParse from 'remark-parse';
import remarkRehype, { Options as RemarkRehypeOptions } from 'remark-rehype';
import rehypeSanitize from 'rehype-sanitize';
import rehypeSanitize, { defaultSchema } from 'rehype-sanitize';
import rehypeHighlight, { Options as RehypeHighlightOptions } from 'rehype-highlight';
import rehypeReact, { Options as RehypeReactOptions } from 'rehype-react';
import { all } from 'lowlight';
@ -10,33 +10,112 @@ import { Fragment, jsx, jsxs } from 'react/jsx-runtime';
import { MarkPostString } from '@/components/dummyPost';
import { raleway, roboto, nunito } from "@/app/fonts";
import rehypeRaw from "rehype-raw";
import Image from "next/image";
export default async function Mark() {
let content = await MarkPostString();
let result = await unified()
.use(remarkParse)
.use(remarkGfm)
.use(remarkRehype, { allowDangerousHtml: true } as RemarkRehypeOptions)
.use(rehypeRaw)
.use(rehypeSanitize)
.use(rehypeHighlight, {
languages: all,
} as RehypeHighlightOptions)
.use(rehypeReact, {
Fragment: Fragment,
jsx: jsx,
jsxs: jsxs,
components: {
h1: props => <h1 className={`${raleway.className} mx-auto w-224 text-4xl`}>{props.children}</h1>,
h2: props => <h2 className={`${raleway.className} mx-auto mt-6 w-224 text-3xl`}>{props.children}</h2>,
h3: props => <h3 className={`${raleway.className} mx-auto mt-4 w-224 text-2xl`}>{props.children}</h3>,
h4: props => <h4 className={`${raleway.className} mx-auto mt-3 w-224 text-xl`}>{props.children}</h4>,
p: props => <p className={`${nunito.className} mx-auto mt-2 w-224`}>{props.children}</p>,
pre: props => <div className={`w-224 mx-auto mt-2`}><pre>{props.children}</pre></div>,
hr: props => <hr className={`mx-auto w-224 mt-6`} />
.use(remarkParse)
.use(remarkGfm)
.use(remarkRehype, { allowDangerousHtml: true } as RemarkRehypeOptions)
.use(rehypeRaw)
.use(rehypeSanitize, {
...defaultSchema,
tagNames: [
...(defaultSchema.tagNames || []),
'figure',
'figcaption',
]
})
.use(rehypeHighlight, {
languages: all,
} as RehypeHighlightOptions)
.use(rehypeReact, {
Fragment: Fragment,
jsx: jsx,
jsxs: jsxs,
passNode: true,
components: {
h1: (props) => (
<h1 className={`${raleway.className} mx-auto w-224 text-4xl`}>
{props.children}
</h1>
),
h2: (props) => (
<h2 className={`${raleway.className} mx-auto mt-6 w-224 text-3xl`}>
{props.children}
</h2>
),
h3: (props) => (
<h3 className={`${raleway.className} mx-auto mt-4 w-224 text-2xl`}>
{props.children}
</h3>
),
h4: (props) => (
<h4 className={`${raleway.className} mx-auto mt-3 w-224 text-xl`}>
{props.children}
</h4>
),
p: (props) => (
<p className={`${nunito.className} mx-auto mt-2 w-224`}>
{props.children}
</p>
),
pre: (props) => (
<div className={`w-224 mx-auto mt-2`}>
<pre>{props.children}</pre>
</div>
),
hr: (props) => <hr className={`mx-auto w-224 mt-6`} />,
img: (props) => {
let src: string = "";
let alt: string = "";
if (typeof props.src === "undefined") {
src = `https://${process.env.ASSETS_DOMAIN}/broken-image.svg`;
} else {
src = props.src;
}
} as RehypeReactOptions)
.process(content);
if (typeof props.alt === "string") {
alt = props.alt;
}
if (
typeof props.width === "undefined" ||
typeof props.height === "undefined"
) {
return (
<Image src={src} alt={alt} className={`mx-auto`} />
);
} else {
return (
<Image
src={src}
alt={alt}
className={`mx-auto`}
width={
typeof props.width === "string"
? parseInt(props.width, 10)
: props.width
}
height={
typeof props.height === "string"
? parseInt(props.height, 10)
: props.height
}
/>
);
}
},
figcaption: (props) => (
<figcaption className={`${nunito.className} text-center mb-6`}>
{props.children}
</figcaption>
),
},
} as RehypeReactOptions)
.process(content);
return result.result;
}

View File

@ -7,7 +7,7 @@ export default function Home() {
<div className={`flex flex-col`}>
<div className={`grid grid-rows-1 grid-cols-1 justify-items-center`}>
<Image
src={`https://assets.suyono.me/placeholder.webp`}
src={`https://${process.env.ASSETS_DOMAIN}/placeholder.webp`}
alt={`blog cover`}
className={`object-cover col-start-1 row-start-1 w-screen h-192 z-0`}
width={1581}
@ -31,7 +31,7 @@ export default function Home() {
className={`flex flex-row max-w-4xl items-center`}
>
<Image
src="https://assets.suyono.me/pthumb.webp"
src={`https://${process.env.ASSETS_DOMAIN}/pthumb.webp`}
alt="post thumbnail"
width={454}
height={341}

View File

@ -199,3 +199,139 @@ Google Chrome and most Chromium-based (e.g., Vivaldi, Microsoft Edge) browsers i
the operating system key management. So when you open the setting for certificate management, an external window
will open.
<figure>
<img alt="MacOS Keychain Access" src="https://assets.suyono.me/post/nginx-ssl-client-certificate-verification-manage-access-to-a-site/mac_keychain_1.png" width="740" height="483">
<figcaption>MacOS Keychain Access Window, accessible from settings page</figcaption>
</figure>
On Mac, it is called Keychain Access. To add a certificate, drag the pfx file onto Keychain Access. You'll need to
input the exact export password when you convert the crt file to pfx/p12 format.
When you click Manage device certificate from the browser setting page, this window will open on Windows. You can import
the pfx file using this window.
<figure>
<img alt="Windows certificate dialog" src="https://assets.suyono.me/post/nginx-ssl-client-certificate-verification-manage-access-to-a-site/certificates.png" width="503" height="467">
<figcaption>Certificates dialog on Widows, open from chrome settings page</figcaption>
</figure>
Alternatively, you can use the certmgr to import the certificate. You can open it from the Windows setting or Control Panel.
<figure>
<img alt="Windows certificates manager" src="https://assets.suyono.me/post/nginx-ssl-client-certificate-verification-manage-access-to-a-site/certmgr.png" width="626" height="444">
<figcaption>Windows certificates manager, accessible from Control Panel</figcaption>
</figure>
### Mozilla Firefox
Firefox has its own Certificate Manager dialog. You can import and manage the certificate from it. It also connects to
the operating system certificate management.
<figure>
<img alt="Firefox certificates manager" src="https://assets.suyono.me/post/nginx-ssl-client-certificate-verification-manage-access-to-a-site/firefox_certificate_manager_1.png" width="740" height="441">
<figcaption>Mozilla Firefox Certificate Manager</figcaption>
</figure>
---
## Testing
You can use any browser or tool, like cURL, to test the client certificate verification setup. If your client
certificate verification succeeds, you can open the page using a browser. If your browser shows something like
403 Forbidden, it means either your browser does not have the certificate or something wrong in your setup.
### cURL
Without a valid client certificate
```sh
curl -v https://www.example.com/
```
response
```
> GET / HTTP/2
> Host: www.example.com
> user-agent: curl/7.74.0
> accept: */*
>
< HTTP/2 403
< server: nginx
< date: Wed, 12 Jul 2023 04:54:02 GMT
< content-type: text/html
< content-length: 146
<
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>
```
With a valid client certificate
```sh
curl --cert user.crt --key user.key -v https://www.example.com/
```
response
```
> GET / HTTP/2
> Host: www.example.com
> user-agent: curl/7.74.0
> accept: */*
>
< HTTP/2 200
< server: nginx
.
.
.
snipped
```
---
## Revoking Access
This setup recognizes users by the certificate they are using. Revoking access here means revoking the users'
certificates. We can achieve this by leveraging OpenSSL's CRL feature. To use it, we need to have the CA database.
I explained how to set it up in the section above.
### Revoke client certificate
```sh
openssl ca -config ca.cnf -revoke user.crt
```
### Generate CRL file
```sh
openssl ca -config ca.cnf -gencrl -out crl.pem
```
### Verifying CRL file
```sh
openssl crl -in crl.pem -noout -text
```
### Nginx configuration for CRL
You need to add the `ssl_crl` directive in the Nginx configuration file, as shown in the example below.
```nginx
....
ssl_client_certificate /path/to/client/verification/ca.crt;
ssl_verify_client optional;
ssl_verify_depth 2;
ssl_crl /path/to/crl.pem; # configure nginx to read the crl file
root /usr/share/nginx/html;
....
```