wip: completed the content, move on to post cover etc
This commit is contained in:
parent
7252456dd4
commit
0d09e0d44f
1
.env
1
.env
@ -1 +1,2 @@
|
|||||||
DUMMY_HTML_DIR=./development-test-data-dir/
|
DUMMY_HTML_DIR=./development-test-data-dir/
|
||||||
|
ASSETS_DOMAIN=assets.suyono.me
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { unified } from 'unified';
|
|||||||
import remarkGfm from 'remark-gfm';
|
import remarkGfm from 'remark-gfm';
|
||||||
import remarkParse from 'remark-parse';
|
import remarkParse from 'remark-parse';
|
||||||
import remarkRehype, { Options as RemarkRehypeOptions } from 'remark-rehype';
|
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 rehypeHighlight, { Options as RehypeHighlightOptions } from 'rehype-highlight';
|
||||||
import rehypeReact, { Options as RehypeReactOptions } from 'rehype-react';
|
import rehypeReact, { Options as RehypeReactOptions } from 'rehype-react';
|
||||||
import { all } from 'lowlight';
|
import { all } from 'lowlight';
|
||||||
@ -10,6 +10,7 @@ import { Fragment, jsx, jsxs } from 'react/jsx-runtime';
|
|||||||
import { MarkPostString } from '@/components/dummyPost';
|
import { MarkPostString } from '@/components/dummyPost';
|
||||||
import { raleway, roboto, nunito } from "@/app/fonts";
|
import { raleway, roboto, nunito } from "@/app/fonts";
|
||||||
import rehypeRaw from "rehype-raw";
|
import rehypeRaw from "rehype-raw";
|
||||||
|
import Image from "next/image";
|
||||||
|
|
||||||
export default async function Mark() {
|
export default async function Mark() {
|
||||||
let content = await MarkPostString();
|
let content = await MarkPostString();
|
||||||
@ -18,7 +19,14 @@ export default async function Mark() {
|
|||||||
.use(remarkGfm)
|
.use(remarkGfm)
|
||||||
.use(remarkRehype, { allowDangerousHtml: true } as RemarkRehypeOptions)
|
.use(remarkRehype, { allowDangerousHtml: true } as RemarkRehypeOptions)
|
||||||
.use(rehypeRaw)
|
.use(rehypeRaw)
|
||||||
.use(rehypeSanitize)
|
.use(rehypeSanitize, {
|
||||||
|
...defaultSchema,
|
||||||
|
tagNames: [
|
||||||
|
...(defaultSchema.tagNames || []),
|
||||||
|
'figure',
|
||||||
|
'figcaption',
|
||||||
|
]
|
||||||
|
})
|
||||||
.use(rehypeHighlight, {
|
.use(rehypeHighlight, {
|
||||||
languages: all,
|
languages: all,
|
||||||
} as RehypeHighlightOptions)
|
} as RehypeHighlightOptions)
|
||||||
@ -26,15 +34,86 @@ export default async function Mark() {
|
|||||||
Fragment: Fragment,
|
Fragment: Fragment,
|
||||||
jsx: jsx,
|
jsx: jsx,
|
||||||
jsxs: jsxs,
|
jsxs: jsxs,
|
||||||
|
passNode: true,
|
||||||
components: {
|
components: {
|
||||||
h1: props => <h1 className={`${raleway.className} mx-auto w-224 text-4xl`}>{props.children}</h1>,
|
h1: (props) => (
|
||||||
h2: props => <h2 className={`${raleway.className} mx-auto mt-6 w-224 text-3xl`}>{props.children}</h2>,
|
<h1 className={`${raleway.className} mx-auto w-224 text-4xl`}>
|
||||||
h3: props => <h3 className={`${raleway.className} mx-auto mt-4 w-224 text-2xl`}>{props.children}</h3>,
|
{props.children}
|
||||||
h4: props => <h4 className={`${raleway.className} mx-auto mt-3 w-224 text-xl`}>{props.children}</h4>,
|
</h1>
|
||||||
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>,
|
h2: (props) => (
|
||||||
hr: props => <hr className={`mx-auto w-224 mt-6`} />
|
<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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
} as RehypeReactOptions)
|
||||||
.process(content);
|
.process(content);
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@ export default function Home() {
|
|||||||
<div className={`flex flex-col`}>
|
<div className={`flex flex-col`}>
|
||||||
<div className={`grid grid-rows-1 grid-cols-1 justify-items-center`}>
|
<div className={`grid grid-rows-1 grid-cols-1 justify-items-center`}>
|
||||||
<Image
|
<Image
|
||||||
src={`https://assets.suyono.me/placeholder.webp`}
|
src={`https://${process.env.ASSETS_DOMAIN}/placeholder.webp`}
|
||||||
alt={`blog cover`}
|
alt={`blog cover`}
|
||||||
className={`object-cover col-start-1 row-start-1 w-screen h-192 z-0`}
|
className={`object-cover col-start-1 row-start-1 w-screen h-192 z-0`}
|
||||||
width={1581}
|
width={1581}
|
||||||
@ -31,7 +31,7 @@ export default function Home() {
|
|||||||
className={`flex flex-row max-w-4xl items-center`}
|
className={`flex flex-row max-w-4xl items-center`}
|
||||||
>
|
>
|
||||||
<Image
|
<Image
|
||||||
src="https://assets.suyono.me/pthumb.webp"
|
src={`https://${process.env.ASSETS_DOMAIN}/pthumb.webp`}
|
||||||
alt="post thumbnail"
|
alt="post thumbnail"
|
||||||
width={454}
|
width={454}
|
||||||
height={341}
|
height={341}
|
||||||
|
|||||||
136
dummies/test1.md
136
dummies/test1.md
@ -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
|
the operating system key management. So when you open the setting for certificate management, an external window
|
||||||
will open.
|
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;
|
||||||
|
....
|
||||||
|
```
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user