yeziruo

利欲驱人万火牛 江湖浪迹一沙鸥

前言

本文不是Lego使用教程。

由于SSL证书一年也就申请给几次,所以一般我都是手动去配置申请,上次介绍了Certbot提供acme模块用法,本文将介绍lego这个ACME客户端所提供的的库的用法。基本上重新造了个轮子,没有去用内部具体的接口。

实现

package main

import (
    "crypto"
    "crypto/x509"
    "encoding/pem"
    "github.com/go-acme/lego/v4/certcrypto"
    "github.com/go-acme/lego/v4/certificate"
    "github.com/go-acme/lego/v4/challenge/dns01"
    "github.com/go-acme/lego/v4/lego"
    "github.com/go-acme/lego/v4/log"
    "github.com/go-acme/lego/v4/registration"
    "io/ioutil"
    "time"
)

// 参见: https://pkg.go.dev/github.com/go-acme/lego/v4@v4.8.0/registration#User
type AcmeUser struct {
    Email        string
    Registration *registration.Resource
    key          crypto.PrivateKey
}

func (u *AcmeUser) GetEmail() string {
    return u.Email
}

func (u *AcmeUser) GetRegistration() *registration.Resource {
    return u.Registration
}
func (u *AcmeUser) GetPrivateKey() crypto.PrivateKey {
    return u.key
}

// 实现 Provider 接口
// 参见: https://pkg.go.dev/github.com/go-acme/lego/v4/challenge@v4.8.0#Provider
// lego本身提供一些DNS服务商的接口,但我一般都是手动申请
type plainDnsProvider struct{}

func (p *plainDnsProvider) Present(domain, token, keyAuth string) error {
    log.Infof("domain: _acme-challenge.%s token: %s", domain, token)
    return nil
}

func (p *plainDnsProvider) CleanUp(domain, token, keyAuth string) error {
    return nil
}

func main() {
    // 本地ACME测试用
    // httpClient := &http.Client{
    //     Transport: &http.Transport{
    //         TLSClientConfig: &tls.Config{InsecureSkipVerify: true
    //     },
    // }}

    key, err := ioutil.ReadFile("account_private.key")
    if err != nil {
        panic(err)
    }
    block, _ := pem.Decode(key)
    priKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
    if err != nil {
        panic(err)
    }

    // 加载账户信息
    user := AcmeUser{
        Email: "local@test.com",
        key:   priKey,
    }
    config := lego.NewConfig(&user)
    // Pebble 默认地址
    // config.CADirURL = "https://127.0.0.1:14000/dir"
    // config.CADirURL = "https://api.buypass.com/acme/directory"
    config.CADirURL = "https://acme-v02.api.letsencrypt.org/directory"
    config.UserAgent = "acm_go/0.0.1"
    // 秘钥类型
    config.Certificate.KeyType = certcrypto.RSA2048
    // 本地测试用
    // config.HTTPClient = httpClient

    // 新建客户端
    client, err := lego.NewClient(config)
    if err != nil {
        panic(err)
    }

    // 账户注册
    reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
    // 使用秘钥查找账户
    // reg, err := client.Registration.ResolveAccountByKey()
    if err != nil {
        panic(err)
    }
    user.Registration = reg

    // 生成证书请求
    request := certificate.ObtainRequest{
        Domains: []string{"yajyusenpai.coat.co.jp"},
        // 证书链
        Bundle: true,
    }

    dnsProvider := plainDnsProvider{}
    // dns.NewDNSChallengeProviderByName(provider_name)
    // dnspodConfig := dnspod.Config{config...}
    // dnspodProvider := dnspod.NewDNSProviderConfig(&dnspodConfig)

    // 以DNS方式验证
    err = client.Challenge.SetDNS01Provider(&dnsProvider, dns01.AddDNSTimeout(6*time.Minute))
    if err != nil {
        panic(err)
    }

    // 自动轮询
    certificates, err := client.Certificate.Obtain(request)
    if err != nil {
        panic(err)
    }

    // 导出
    _ = ioutil.WriteFile("certificate.crt", certificates.Certificate, 0755)
    _ = ioutil.WriteFile("certificate_private.key", certificates.PrivateKey, 0755)
}

220707063204.jpg

暂无评论

正在回复ID为 ??? 的评论

© 2013-2022 yeziruo. All Rights Reserved. Start5 theme by yeziruo.

CC BY-NC-SA 3.0 CN