详解如何使用go-acme/lego实现自动签发证书
作者:AlpsMonaco
相关背景知识
Let's Encrypt
Let's Encrypt是一个于2015年三季度推出的数字证书认证机构,旨在以自动化流程消除手动创建和安装证书的复杂流程,并推广使万维网服务器的加密连接无所不在,为安全网站提供免费的传输层安全性协议证书。
ACME
ACME,即自动自动证书管理环境(Automatic Certificate Management Environment),是一种协议,用于自动颁发和更新证书,无需人工干预。
互联网安全研究小组 (ISRG) 最初为自己的证书服务设计了ACME协议。证书颁发机构Let’s Encrypt通过ACME协议免费提供DV证书。如今,各种其他的CA、PKI供应商和浏览器都支持ACME协议,支持不同类型的证书。
go-acme/lego
一个用go语言写的acme客户端和go语言库。下文简称为 lego
。
使用 lego 客户端
安装
如果有golang开发环境可以使用以下命令安装lego
go install github.com/go-acme/lego/v4/cmd/lego@latest
如果没有golang开发环境可前往 github.com/go-acme/lego/releases 下载最新cli客户端
签发证书
签发证书需要验证域名的所有权,acme
协议提供了两种方法来验证你的域名所有权,分别是http服务器验证和dns验证。
http服务器验证
使用该方法验证需要有一台服务器,该服务器要有公网ip。同时还需要拥有服务器的root权限,才能监听80和443端口。
假设需要部署证书的域名为 example.com ,我们需要先配置 example.com 指向该服务器的公网ip,然后在服务器上执行
lego --email="you@example.com" --domains="example.com" --http run
该命令启动一个http服务器,监听80/443端口。
随后Let's Encrypt
会根据域名(example.com)访问服务器的80/443端口,验证域名的所有权。这个过程是自动化的,只需要等待即可。
验证通过后会下发证书到 ./.lego/certificates
里,证书的有效期为3个月。
dns验证
lego
强大的地方便是集成了几乎所有常用的云厂商,如CloudFlare、阿里云和腾讯云等的服务API。只需要设置API_KEY和API_SECRET便可以自动帮你完成DNS验证。
这边以腾讯云为例:
执行以下命令:
TENCENTCLOUD_SECRET_ID=abcdefghijklmnopqrstuvwx \ TENCENTCLOUD_SECRET_KEY=your-secret-key \ lego --email you@example.com --dns tencentcloud --domains my.example.org run
该命令会调用腾讯云的后台API,为example.com
填写DNS验证信息;Let's Encrypt
验证通过之后,下发证书到./.lego/certificates
,同时也会自动帮你删除该DNS验证信息。
使用lego库
我们也可以使用lego
库来生成证书,或者做一些自动化证书生成然后部署的二次开发。lego
库同样也支持http服务器验证和dns验证,下面给出完整可用代码。
50-62行为腾讯云dns验证部分,64-73为http服务器验证部分,二选一即可。
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-腾讯云验证的方式结束----------- // 使用http服务器验证的方式,注释上面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服务器验证的方式结束----------- 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) } }
到此这篇关于详解如何使用go-acme/lego实现自动签发证书的文章就介绍到这了,更多相关go自动签发证书内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!