详解如何使用go-acme/lego实现自动签发证书

 更新时间:2024年03月10日 10:36:15   作者:AlpsMonaco  
这篇文章主要为大家详细介绍了如何使用 go-acme/lego 的客户端或库完成证书的自动签发,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

相关背景知识

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自动签发证书内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • go goroutine 怎样进行错误处理

    go goroutine 怎样进行错误处理

    在 Go 语言程序开发中,goroutine 的使用是比较频繁的,因此在日常编码的时候 goroutine 里的错误处理,怎么做会比较好呢,本文就来详细介绍一下
    2021-07-07
  • Go语言中字符串的查找方法小结

    Go语言中字符串的查找方法小结

    这篇文章主要介绍了Go语言中字符串的查找方法小结,示例的main函数都是导入strings包然后使用其中的方法,需要的朋友可以参考下
    2015-10-10
  • Go语言实现字符串搜索算法Boyer-Moore

    Go语言实现字符串搜索算法Boyer-Moore

    Boyer-Moore 算法是一种非常高效的字符串搜索算法,被广泛的应用于多种字符串搜索场景,下面我们就来学习一下如何利用Go语言实现这一字符串搜索算法吧
    2023-11-11
  • GO语言并发编程之互斥锁、读写锁详解

    GO语言并发编程之互斥锁、读写锁详解

    这篇文章主要介绍了GO语言并发编程之互斥锁、读写锁详解,本文是GO并发编程实战一书的样章,详细讲解了互斥锁、读写锁,然后给出了一个完整示例,需要的朋友可以参考下
    2014-11-11
  • Go语言WaitGroup使用时需要注意的坑

    Go语言WaitGroup使用时需要注意的坑

    Go语言中WaitGroup的用途是它能够一直等到所有的goroutine执行完成,并且阻塞主线程的执行,直到所有的goroutine执行完成。之前一直使用也没有问题,但最近通过同事的一段代码引起了关于WaitGroup的注意,下面这篇文章就介绍了WaitGroup使用时需要注意的坑及填坑。
    2016-12-12
  • golang中配置 sql.DB获得更好的性能

    golang中配置 sql.DB获得更好的性能

    这篇文章主要介绍了golang中如何配置 sql.DB获得更好的性能,在这篇文章中,我想准确解释这些设置的作用,并展示它们可能产生的(积极和消极)影响,需要的朋友可以参考下
    2023-10-10
  • Go语言基础之网络编程全面教程示例

    Go语言基础之网络编程全面教程示例

    这篇文章主要为大家介绍了Go语言基础之网络编程全面教程示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • Go常用标准库之fmt的简介与使用详解

    Go常用标准库之fmt的简介与使用详解

    fmt 是 Go 语言中的一个常用标准库,它用于格式化输入和输出数据,这篇文章主要为大家介绍了fmt的基本使用,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-10-10
  • golang channel读取数据的几种情况

    golang channel读取数据的几种情况

    本文主要介绍了golang channel读取数据的几种情况,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • 利用ChatGPT编写一个Golang图像压缩函数

    利用ChatGPT编写一个Golang图像压缩函数

    这篇文章主要为大家详细介绍了如何利用ChatGPT帮我们写了一个Golang图像压缩函数,文中的示例代码简洁易懂,感兴趣的小伙伴可以尝试一下
    2023-04-04

最新评论