詳解如何使用go-acme/lego實現(xiàn)自動簽發(fā)證書
相關(guān)背景知識
Let's Encrypt
Let's Encrypt是一個于2015年三季度推出的數(shù)字證書認(rèn)證機(jī)構(gòu),旨在以自動化流程消除手動創(chuàng)建和安裝證書的復(fù)雜流程,并推廣使萬維網(wǎng)服務(wù)器的加密連接無所不在,為安全網(wǎng)站提供免費的傳輸層安全性協(xié)議證書。
ACME
ACME,即自動自動證書管理環(huán)境(Automatic Certificate Management Environment),是一種協(xié)議,用于自動頒發(fā)和更新證書,無需人工干預(yù)。
互聯(lián)網(wǎng)安全研究小組 (ISRG) 最初為自己的證書服務(wù)設(shè)計了ACME協(xié)議。證書頒發(fā)機(jī)構(gòu)Let’s Encrypt通過ACME協(xié)議免費提供DV證書。如今,各種其他的CA、PKI供應(yīng)商和瀏覽器都支持ACME協(xié)議,支持不同類型的證書。
go-acme/lego
一個用go語言寫的acme客戶端和go語言庫。下文簡稱為 lego。
使用 lego 客戶端
安裝
如果有g(shù)olang開發(fā)環(huán)境可以使用以下命令安裝lego
go install github.com/go-acme/lego/v4/cmd/lego@latest
如果沒有g(shù)olang開發(fā)環(huán)境可前往 github.com/go-acme/lego/releases 下載最新cli客戶端
簽發(fā)證書
簽發(fā)證書需要驗證域名的所有權(quán),acme協(xié)議提供了兩種方法來驗證你的域名所有權(quán),分別是http服務(wù)器驗證和dns驗證。
http服務(wù)器驗證
使用該方法驗證需要有一臺服務(wù)器,該服務(wù)器要有公網(wǎng)ip。同時還需要擁有服務(wù)器的root權(quán)限,才能監(jiān)聽80和443端口。
假設(shè)需要部署證書的域名為 example.com ,我們需要先配置 example.com 指向該服務(wù)器的公網(wǎng)ip,然后在服務(wù)器上執(zhí)行
lego --email="you@example.com" --domains="example.com" --http run
該命令啟動一個http服務(wù)器,監(jiān)聽80/443端口。
隨后Let's Encrypt會根據(jù)域名(example.com)訪問服務(wù)器的80/443端口,驗證域名的所有權(quán)。這個過程是自動化的,只需要等待即可。
驗證通過后會下發(fā)證書到 ./.lego/certificates 里,證書的有效期為3個月。
dns驗證
lego強(qiáng)大的地方便是集成了幾乎所有常用的云廠商,如CloudFlare、阿里云和騰訊云等的服務(wù)API。只需要設(shè)置API_KEY和API_SECRET便可以自動幫你完成DNS驗證。
這邊以騰訊云為例:
執(zhí)行以下命令:
TENCENTCLOUD_SECRET_ID=abcdefghijklmnopqrstuvwx \ TENCENTCLOUD_SECRET_KEY=your-secret-key \ lego --email you@example.com --dns tencentcloud --domains my.example.org run
該命令會調(diào)用騰訊云的后臺API,為example.com填寫DNS驗證信息;Let's Encrypt驗證通過之后,下發(fā)證書到./.lego/certificates,同時也會自動幫你刪除該DNS驗證信息。
使用lego庫
我們也可以使用lego庫來生成證書,或者做一些自動化證書生成然后部署的二次開發(fā)。lego庫同樣也支持http服務(wù)器驗證和dns驗證,下面給出完整可用代碼。
50-62行為騰訊云dns驗證部分,64-73為http服務(wù)器驗證部分,二選一即可。
package main
import (
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"fmt"
"github.com/go-acme/lego/v4/certcrypto"
"github.com/go-acme/lego/v4/certificate"
"github.com/go-acme/lego/v4/lego"
"github.com/go-acme/lego/v4/providers/dns/tencentcloud"
"github.com/go-acme/lego/v4/registration"
"log"
"os"
)
type MyUser struct {
Email string
Registration *registration.Resource
key crypto.PrivateKey
}
func (u *MyUser) GetEmail() string {
return u.Email
}
func (u MyUser) GetRegistration() *registration.Resource {
return u.Registration
}
func (u *MyUser) GetPrivateKey() crypto.PrivateKey {
return u.key
}
func main() {
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
log.Fatal(err)
}
myUser := MyUser{
Email: "you@example.com",
key: privateKey,
}
config := lego.NewConfig(&myUser)
config.Certificate.KeyType = certcrypto.RSA2048
client, err := lego.NewClient(config)
if err != nil {
log.Fatal(err)
}
// 使用dns驗證的方式,這邊以騰訊云為例子。
cfg := tencentcloud.NewDefaultConfig()
cfg.SecretID = "abcdefghijklmnopqrstuvwx"
cfg.SecretKey = "your-secret-key"
p, err := tencentcloud.NewDNSProviderConfig(cfg)
if err != nil {
log.Fatal(err)
}
err = client.Challenge.SetDNS01Provider(p)
if err != nil {
log.Fatal(err)
}
// ---------使用dns-騰訊云驗證的方式結(jié)束-----------
// 使用http服務(wù)器驗證的方式,注釋上面dns驗證的代碼部分,取消下面http驗證的代碼注釋部分
// err = client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", "80"))
// if err != nil {
// log.Fatal(err)
// }
// err = client.Challenge.SetTLSALPN01Provider(tlsalpn01.NewProviderServer("", "443"))
// if err != nil {
// log.Fatal(err)
// }
//-----------使用http服務(wù)器驗證的方式結(jié)束-----------
reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
if err != nil {
log.Fatal(err)
}
myUser.Registration = reg
request := certificate.ObtainRequest{
Domains: []string{"sd.pigudaxiang.cn"},
Bundle: true,
}
certificates, err := client.Certificate.Obtain(request)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%#v\n", certificates)
err = os.WriteFile("PrivateKey", certificates.PrivateKey, os.ModePerm)
if err != nil {
log.Print(err)
}
err = os.WriteFile("Certificate", certificates.Certificate, os.ModePerm)
if err != nil {
log.Print(err)
}
err = os.WriteFile("IssuerCertificate", certificates.IssuerCertificate, os.ModePerm)
if err != nil {
log.Print(err)
}
err = os.WriteFile("CSR", certificates.CSR, os.ModePerm)
if err != nil {
log.Print(err)
}
}
到此這篇關(guān)于詳解如何使用go-acme/lego實現(xiàn)自動簽發(fā)證書的文章就介紹到這了,更多相關(guān)go自動簽發(fā)證書內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
go?mode?tidy出現(xiàn)報錯go:?warning:?“all“?matched?no?package
使用go的時候我們一般都會使用go?mode管理,下面這篇文章主要給大家介紹了關(guān)于go?mode?tidy出現(xiàn)報錯go:?warning:?“all“?matched?no?packages的解決方法,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08
Go1.16新特性embed打包靜態(tài)資源文件實現(xiàn)
這篇文章主要為大家介紹了Go?1.16新特性embed打包靜態(tài)資源文件的實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
Go?json自定義Unmarshal避免判斷nil示例詳解
這篇文章主要為大家介紹了Go?json自定義Unmarshal避免判斷nil示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
golang?chan傳遞數(shù)據(jù)的性能開銷詳解
這篇文章主要為大家詳細(xì)介紹了Golang中chan在接收和發(fā)送數(shù)據(jù)時因為“復(fù)制”而產(chǎn)生的開銷,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2024-01-01

