mirror of
https://github.com/TeaOSLab/EdgeAPI.git
synced 2025-11-03 15:00:27 +08:00
[SSL证书]免费证书申请增加HTTP认证方式
This commit is contained in:
3
internal/acme/auth_callback.go
Normal file
3
internal/acme/auth_callback.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
package acme
|
||||||
|
|
||||||
|
type AuthCallback func(domain, token, keyAuth string)
|
||||||
23
internal/acme/http_provider.go
Normal file
23
internal/acme/http_provider.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package acme
|
||||||
|
|
||||||
|
type HTTPProvider struct {
|
||||||
|
onAuth AuthCallback
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHTTPProvider(onAuth AuthCallback) *HTTPProvider {
|
||||||
|
return &HTTPProvider{
|
||||||
|
onAuth: onAuth,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *HTTPProvider) Present(domain, token, keyAuth string) error {
|
||||||
|
if this.onAuth != nil {
|
||||||
|
this.onAuth(domain, token, keyAuth)
|
||||||
|
}
|
||||||
|
//http01.ChallengePath()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *HTTPProvider) CleanUp(domain, token, keyAuth string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -14,7 +14,8 @@ import (
|
|||||||
type Request struct {
|
type Request struct {
|
||||||
debug bool
|
debug bool
|
||||||
|
|
||||||
task *Task
|
task *Task
|
||||||
|
onAuth AuthCallback
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRequest(task *Task) *Request {
|
func NewRequest(task *Task) *Request {
|
||||||
@@ -27,7 +28,23 @@ func (this *Request) Debug() {
|
|||||||
this.debug = true
|
this.debug = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *Request) OnAuth(onAuth AuthCallback) {
|
||||||
|
this.onAuth = onAuth
|
||||||
|
}
|
||||||
|
|
||||||
func (this *Request) Run() (certData []byte, keyData []byte, err error) {
|
func (this *Request) Run() (certData []byte, keyData []byte, err error) {
|
||||||
|
switch this.task.AuthType {
|
||||||
|
case AuthTypeDNS:
|
||||||
|
return this.runDNS()
|
||||||
|
case AuthTypeHTTP:
|
||||||
|
return this.runHTTP()
|
||||||
|
default:
|
||||||
|
err = errors.New("invalid task type '" + this.task.AuthType + "'")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Request) runDNS() (certData []byte, keyData []byte, err error) {
|
||||||
if !this.debug {
|
if !this.debug {
|
||||||
acmelog.Logger = log.New(ioutil.Discard, "", log.LstdFlags)
|
acmelog.Logger = log.New(ioutil.Discard, "", log.LstdFlags)
|
||||||
}
|
}
|
||||||
@@ -92,3 +109,57 @@ func (this *Request) Run() (certData []byte, keyData []byte, err error) {
|
|||||||
|
|
||||||
return certResource.Certificate, certResource.PrivateKey, nil
|
return certResource.Certificate, certResource.PrivateKey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *Request) runHTTP() (certData []byte, keyData []byte, err error) {
|
||||||
|
if !this.debug {
|
||||||
|
acmelog.Logger = log.New(ioutil.Discard, "", log.LstdFlags)
|
||||||
|
}
|
||||||
|
|
||||||
|
if this.task.User == nil {
|
||||||
|
err = errors.New("'user' must not be nil")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
config := lego.NewConfig(this.task.User)
|
||||||
|
config.Certificate.KeyType = certcrypto.RSA2048
|
||||||
|
|
||||||
|
client, err := lego.NewClient(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注册用户
|
||||||
|
resource := this.task.User.GetRegistration()
|
||||||
|
if resource != nil {
|
||||||
|
resource, err = client.Registration.QueryRegistration()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resource, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
err = this.task.User.Register(resource)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = client.Challenge.SetHTTP01Provider(NewHTTPProvider(this.onAuth))
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 申请证书
|
||||||
|
request := certificate.ObtainRequest{
|
||||||
|
Domains: this.task.Domains,
|
||||||
|
Bundle: true,
|
||||||
|
}
|
||||||
|
certResource, err := client.Certificate.Obtain(request)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return certResource.Certificate, certResource.PrivateKey, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNewRequest(t *testing.T) {
|
func TestRequest_Run_DNS(t *testing.T) {
|
||||||
privateKey, err := ParsePrivateKeyFromBase64("MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgD3xxDXP4YVqHCfub21Yi3QL1Kvgow23J8CKJ7vU3L4+hRANCAARRl5ZKAlgGRc5RETSMYFCTXvjnePDgjALWgtgfClQGLB2rGyRecJvlesAM6Q7LQrDxVxvxdSQQmPGRqJGiBtjd")
|
privateKey, err := ParsePrivateKeyFromBase64("MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgD3xxDXP4YVqHCfub21Yi3QL1Kvgow23J8CKJ7vU3L4+hRANCAARRl5ZKAlgGRc5RETSMYFCTXvjnePDgjALWgtgfClQGLB2rGyRecJvlesAM6Q7LQrDxVxvxdSQQmPGRqJGiBtjd")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -39,6 +39,7 @@ func TestNewRequest(t *testing.T) {
|
|||||||
|
|
||||||
req := NewRequest(&Task{
|
req := NewRequest(&Task{
|
||||||
User: user,
|
User: user,
|
||||||
|
Type: TaskTypeDNS,
|
||||||
DNSProvider: dnsProvider,
|
DNSProvider: dnsProvider,
|
||||||
DNSDomain: "yun4s.cn",
|
DNSDomain: "yun4s.cn",
|
||||||
Domains: []string{"yun4s.cn"},
|
Domains: []string{"yun4s.cn"},
|
||||||
@@ -51,6 +52,40 @@ func TestNewRequest(t *testing.T) {
|
|||||||
t.Log("key:", string(keyData))
|
t.Log("key:", string(keyData))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRequest_Run_HTTP(t *testing.T) {
|
||||||
|
privateKey, err := ParsePrivateKeyFromBase64("MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgD3xxDXP4YVqHCfub21Yi3QL1Kvgow23J8CKJ7vU3L4+hRANCAARRl5ZKAlgGRc5RETSMYFCTXvjnePDgjALWgtgfClQGLB2rGyRecJvlesAM6Q7LQrDxVxvxdSQQmPGRqJGiBtjd")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
user := NewUser("19644627@qq.com", privateKey, func(resource *registration.Resource) error {
|
||||||
|
resourceJSON, err := json.Marshal(resource)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
t.Log(string(resourceJSON))
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
regResource := []byte(`{"body":{"status":"valid","contact":["mailto:19644627@qq.com"]},"uri":"https://acme-v02.api.letsencrypt.org/acme/acct/103672877"}`)
|
||||||
|
err = user.SetRegistration(regResource)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
req := NewRequest(&Task{
|
||||||
|
User: user,
|
||||||
|
Type: TaskTypeHTTP,
|
||||||
|
Domains: []string{"teaos.cn", "www.teaos.cn", "meloy.cn"},
|
||||||
|
})
|
||||||
|
certData, keyData, err := req.runHTTP()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(string(certData))
|
||||||
|
t.Log(string(keyData))
|
||||||
|
}
|
||||||
|
|
||||||
func testDNSPodProvider() (dnsclients.ProviderInterface, error) {
|
func testDNSPodProvider() (dnsclients.ProviderInterface, error) {
|
||||||
db, err := dbs.Default()
|
db, err := dbs.Default()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -2,9 +2,19 @@ package acme
|
|||||||
|
|
||||||
import "github.com/TeaOSLab/EdgeAPI/internal/dnsclients"
|
import "github.com/TeaOSLab/EdgeAPI/internal/dnsclients"
|
||||||
|
|
||||||
|
type AuthType = string
|
||||||
|
|
||||||
|
const (
|
||||||
|
AuthTypeDNS AuthType = "dns"
|
||||||
|
AuthTypeHTTP AuthType = "http"
|
||||||
|
)
|
||||||
|
|
||||||
type Task struct {
|
type Task struct {
|
||||||
User *User
|
User *User
|
||||||
|
AuthType AuthType
|
||||||
|
Domains []string
|
||||||
|
|
||||||
|
// DNS相关
|
||||||
DNSProvider dnsclients.ProviderInterface
|
DNSProvider dnsclients.ProviderInterface
|
||||||
DNSDomain string
|
DNSDomain string
|
||||||
Domains []string
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package teaconst
|
package teaconst
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Version = "0.0.4"
|
Version = "0.0.5"
|
||||||
|
|
||||||
ProductName = "Edge API"
|
ProductName = "Edge API"
|
||||||
ProcessName = "edge-api"
|
ProcessName = "edge-api"
|
||||||
|
|||||||
54
internal/db/models/acme_authentication_dao.go
Normal file
54
internal/db/models/acme_authentication_dao.go
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
"github.com/iwind/TeaGo/Tea"
|
||||||
|
"github.com/iwind/TeaGo/dbs"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ACMEAuthenticationDAO dbs.DAO
|
||||||
|
|
||||||
|
func NewACMEAuthenticationDAO() *ACMEAuthenticationDAO {
|
||||||
|
return dbs.NewDAO(&ACMEAuthenticationDAO{
|
||||||
|
DAOObject: dbs.DAOObject{
|
||||||
|
DB: Tea.Env,
|
||||||
|
Table: "edgeACMEAuthentications",
|
||||||
|
Model: new(ACMEAuthentication),
|
||||||
|
PkName: "id",
|
||||||
|
},
|
||||||
|
}).(*ACMEAuthenticationDAO)
|
||||||
|
}
|
||||||
|
|
||||||
|
var SharedACMEAuthenticationDAO *ACMEAuthenticationDAO
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
dbs.OnReady(func() {
|
||||||
|
SharedACMEAuthenticationDAO = NewACMEAuthenticationDAO()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建认证信息
|
||||||
|
func (this *ACMEAuthenticationDAO) CreateAuth(taskId int64, domain string, token string, key string) error {
|
||||||
|
op := NewACMEAuthenticationOperator()
|
||||||
|
op.TaskId = taskId
|
||||||
|
op.Domain = domain
|
||||||
|
op.Token = token
|
||||||
|
op.Key = key
|
||||||
|
_, err := this.Save(op)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据令牌查找认证信息
|
||||||
|
func (this *ACMEAuthenticationDAO) FindAuthWithToken(token string) (*ACMEAuthentication, error) {
|
||||||
|
one, err := this.Query().
|
||||||
|
Attr("token", token).
|
||||||
|
DescPk().
|
||||||
|
Find()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if one == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return one.(*ACMEAuthentication), nil
|
||||||
|
}
|
||||||
5
internal/db/models/acme_authentication_dao_test.go
Normal file
5
internal/db/models/acme_authentication_dao_test.go
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
)
|
||||||
24
internal/db/models/acme_authentication_model.go
Normal file
24
internal/db/models/acme_authentication_model.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
// ACME认证
|
||||||
|
type ACMEAuthentication struct {
|
||||||
|
Id uint64 `field:"id"` // ID
|
||||||
|
TaskId uint64 `field:"taskId"` // 任务ID
|
||||||
|
Domain string `field:"domain"` // 域名
|
||||||
|
Token string `field:"token"` // 令牌
|
||||||
|
Key string `field:"key"` // 密钥
|
||||||
|
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||||
|
}
|
||||||
|
|
||||||
|
type ACMEAuthenticationOperator struct {
|
||||||
|
Id interface{} // ID
|
||||||
|
TaskId interface{} // 任务ID
|
||||||
|
Domain interface{} // 域名
|
||||||
|
Token interface{} // 令牌
|
||||||
|
Key interface{} // 密钥
|
||||||
|
CreatedAt interface{} // 创建时间
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewACMEAuthenticationOperator() *ACMEAuthenticationOperator {
|
||||||
|
return &ACMEAuthenticationOperator{}
|
||||||
|
}
|
||||||
1
internal/db/models/acme_authentication_model_ext.go
Normal file
1
internal/db/models/acme_authentication_model_ext.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package models
|
||||||
@@ -115,10 +115,11 @@ func (this *ACMETaskDAO) ListEnabledACMETasks(adminId int64, userId int64, offse
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 创建任务
|
// 创建任务
|
||||||
func (this *ACMETaskDAO) CreateACMETask(adminId int64, userId int64, acmeUserId int64, dnsProviderId int64, dnsDomain string, domains []string, autoRenew bool) (int64, error) {
|
func (this *ACMETaskDAO) CreateACMETask(adminId int64, userId int64, authType acme.AuthType, acmeUserId int64, dnsProviderId int64, dnsDomain string, domains []string, autoRenew bool) (int64, error) {
|
||||||
op := NewACMETaskOperator()
|
op := NewACMETaskOperator()
|
||||||
op.AdminId = adminId
|
op.AdminId = adminId
|
||||||
op.UserId = userId
|
op.UserId = userId
|
||||||
|
op.AuthType = authType
|
||||||
op.AcmeUserId = acmeUserId
|
op.AcmeUserId = acmeUserId
|
||||||
op.DnsProviderId = dnsProviderId
|
op.DnsProviderId = dnsProviderId
|
||||||
op.DnsDomain = dnsDomain
|
op.DnsDomain = dnsDomain
|
||||||
@@ -255,37 +256,55 @@ func (this *ACMETaskDAO) runTaskWithoutLog(taskId int64) (isOk bool, errMsg stri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DNS服务商
|
var acmeTask *acme.Task = nil
|
||||||
dnsProvider, err := SharedDNSProviderDAO.FindEnabledDNSProvider(int64(task.DnsProviderId))
|
if task.AuthType == acme.AuthTypeDNS {
|
||||||
if err != nil {
|
// DNS服务商
|
||||||
errMsg = "查找DNS服务商账号信息时出错:" + err.Error()
|
dnsProvider, err := SharedDNSProviderDAO.FindEnabledDNSProvider(int64(task.DnsProviderId))
|
||||||
return
|
if err != nil {
|
||||||
}
|
errMsg = "查找DNS服务商账号信息时出错:" + err.Error()
|
||||||
if dnsProvider == nil {
|
return
|
||||||
errMsg = "找不到DNS服务商账号"
|
}
|
||||||
return
|
if dnsProvider == nil {
|
||||||
}
|
errMsg = "找不到DNS服务商账号"
|
||||||
providerInterface := dnsclients.FindProvider(dnsProvider.Type)
|
return
|
||||||
if providerInterface == nil {
|
}
|
||||||
errMsg = "暂不支持此类型的DNS服务商 '" + dnsProvider.Type + "'"
|
providerInterface := dnsclients.FindProvider(dnsProvider.Type)
|
||||||
return
|
if providerInterface == nil {
|
||||||
}
|
errMsg = "暂不支持此类型的DNS服务商 '" + dnsProvider.Type + "'"
|
||||||
apiParams, err := dnsProvider.DecodeAPIParams()
|
return
|
||||||
if err != nil {
|
}
|
||||||
errMsg = "解析DNS服务商API参数时出错:" + err.Error()
|
apiParams, err := dnsProvider.DecodeAPIParams()
|
||||||
return
|
if err != nil {
|
||||||
}
|
errMsg = "解析DNS服务商API参数时出错:" + err.Error()
|
||||||
err = providerInterface.Auth(apiParams)
|
return
|
||||||
if err != nil {
|
}
|
||||||
errMsg = "校验DNS服务商API参数时出错:" + err.Error()
|
err = providerInterface.Auth(apiParams)
|
||||||
return
|
if err != nil {
|
||||||
|
errMsg = "校验DNS服务商API参数时出错:" + err.Error()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
acmeTask = &acme.Task{
|
||||||
|
User: remoteUser,
|
||||||
|
AuthType: acme.AuthTypeDNS,
|
||||||
|
DNSProvider: providerInterface,
|
||||||
|
DNSDomain: task.DnsDomain,
|
||||||
|
Domains: task.DecodeDomains(),
|
||||||
|
}
|
||||||
|
} else if task.AuthType == acme.AuthTypeHTTP {
|
||||||
|
acmeTask = &acme.Task{
|
||||||
|
User: remoteUser,
|
||||||
|
AuthType: acme.AuthTypeHTTP,
|
||||||
|
Domains: task.DecodeDomains(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
acmeRequest := acme.NewRequest(&acme.Task{
|
acmeRequest := acme.NewRequest(acmeTask)
|
||||||
User: remoteUser,
|
acmeRequest.OnAuth(func(domain, token, keyAuth string) {
|
||||||
DNSProvider: providerInterface,
|
err := SharedACMEAuthenticationDAO.CreateAuth(taskId, domain, token, keyAuth)
|
||||||
DNSDomain: task.DnsDomain,
|
if err != nil {
|
||||||
Domains: task.DecodeDomains(),
|
logs.Println("[ACME]write authentication to database error: " + err.Error())
|
||||||
|
}
|
||||||
})
|
})
|
||||||
certData, keyData, err := acmeRequest.Run()
|
certData, keyData, err := acmeRequest.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ type ACMETask struct {
|
|||||||
State uint8 `field:"state"` // 状态
|
State uint8 `field:"state"` // 状态
|
||||||
CertId uint64 `field:"certId"` // 生成的证书ID
|
CertId uint64 `field:"certId"` // 生成的证书ID
|
||||||
AutoRenew uint8 `field:"autoRenew"` // 是否自动更新
|
AutoRenew uint8 `field:"autoRenew"` // 是否自动更新
|
||||||
|
AuthType string `field:"authType"` // 认证类型
|
||||||
}
|
}
|
||||||
|
|
||||||
type ACMETaskOperator struct {
|
type ACMETaskOperator struct {
|
||||||
@@ -29,6 +30,7 @@ type ACMETaskOperator struct {
|
|||||||
State interface{} // 状态
|
State interface{} // 状态
|
||||||
CertId interface{} // 生成的证书ID
|
CertId interface{} // 生成的证书ID
|
||||||
AutoRenew interface{} // 是否自动更新
|
AutoRenew interface{} // 是否自动更新
|
||||||
|
AuthType interface{} // 认证类型
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewACMETaskOperator() *ACMETaskOperator {
|
func NewACMETaskOperator() *ACMETaskOperator {
|
||||||
|
|||||||
@@ -637,8 +637,7 @@ func (this *NodeDAO) FindEnabledNodeDNS(nodeId int64) (*Node, error) {
|
|||||||
one, err := this.Query().
|
one, err := this.Query().
|
||||||
State(NodeStateEnabled).
|
State(NodeStateEnabled).
|
||||||
Pk(nodeId).
|
Pk(nodeId).
|
||||||
Attr("isOn", true).
|
Result("id", "name", "dnsRoutes", "clusterId", "isOn").
|
||||||
Result("id", "name", "dnsRoutes", "clusterId").
|
|
||||||
Find()
|
Find()
|
||||||
if err != nil || one == nil {
|
if err != nil || one == nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -199,6 +199,7 @@ func (this *APINode) listenRPC(listener net.Listener, tlsConfig *tls.Config) err
|
|||||||
pb.RegisterDNSServiceServer(rpcServer, &services.DNSService{})
|
pb.RegisterDNSServiceServer(rpcServer, &services.DNSService{})
|
||||||
pb.RegisterACMEUserServiceServer(rpcServer, &services.ACMEUserService{})
|
pb.RegisterACMEUserServiceServer(rpcServer, &services.ACMEUserService{})
|
||||||
pb.RegisterACMETaskServiceServer(rpcServer, &services.ACMETaskService{})
|
pb.RegisterACMETaskServiceServer(rpcServer, &services.ACMETaskService{})
|
||||||
|
pb.RegisterACMEAuthenticationServiceServer(rpcServer, &services.ACMEAuthenticationService{})
|
||||||
err := rpcServer.Serve(listener)
|
err := rpcServer.Serve(listener)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("[API_NODE]start rpc failed: " + err.Error())
|
return errors.New("[API_NODE]start rpc failed: " + err.Error())
|
||||||
|
|||||||
33
internal/rpc/services/service_acme_authentication.go
Normal file
33
internal/rpc/services/service_acme_authentication.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ACME认证相关
|
||||||
|
type ACMEAuthenticationService struct {
|
||||||
|
BaseService
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取Key
|
||||||
|
func (this *ACMEAuthenticationService) FindACMEAuthenticationKeyWithToken(ctx context.Context, req *pb.FindACMEAuthenticationKeyWithTokenRequest) (*pb.FindACMEAuthenticationKeyWithTokenResponse, error) {
|
||||||
|
_, err := this.ValidateNode(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(req.Token) == 0 {
|
||||||
|
return nil, errors.New("'token' should not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
auth, err := models.SharedACMEAuthenticationDAO.FindAuthWithToken(req.Token)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if auth == nil {
|
||||||
|
return &pb.FindACMEAuthenticationKeyWithTokenResponse{Key: ""}, nil
|
||||||
|
}
|
||||||
|
return &pb.FindACMEAuthenticationKeyWithTokenResponse{Key: auth.Key}, nil
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package services
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/acme"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/dnsclients"
|
"github.com/TeaOSLab/EdgeAPI/internal/dnsclients"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
@@ -87,19 +88,22 @@ func (this *ACMETaskService) ListEnabledACMETasks(ctx context.Context, req *pb.L
|
|||||||
CreatedAt: int64(acmeUser.CreatedAt),
|
CreatedAt: int64(acmeUser.CreatedAt),
|
||||||
}
|
}
|
||||||
|
|
||||||
// DNS
|
var pbProvider *pb.DNSProvider
|
||||||
provider, err := models.SharedDNSProviderDAO.FindEnabledDNSProvider(int64(task.DnsProviderId))
|
if task.AuthType == acme.AuthTypeDNS {
|
||||||
if err != nil {
|
// DNS
|
||||||
return nil, err
|
provider, err := models.SharedDNSProviderDAO.FindEnabledDNSProvider(int64(task.DnsProviderId))
|
||||||
}
|
if err != nil {
|
||||||
if provider == nil {
|
return nil, err
|
||||||
continue
|
}
|
||||||
}
|
if provider == nil {
|
||||||
pbProvider := &pb.DNSProvider{
|
continue
|
||||||
Id: int64(provider.Id),
|
}
|
||||||
Name: provider.Name,
|
pbProvider = &pb.DNSProvider{
|
||||||
Type: provider.Type,
|
Id: int64(provider.Id),
|
||||||
TypeName: dnsclients.FindProviderTypeName(provider.Type),
|
Name: provider.Name,
|
||||||
|
Type: provider.Type,
|
||||||
|
TypeName: dnsclients.FindProviderTypeName(provider.Type),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 证书
|
// 证书
|
||||||
@@ -147,6 +151,7 @@ func (this *ACMETaskService) ListEnabledACMETasks(ctx context.Context, req *pb.L
|
|||||||
DnsProvider: pbProvider,
|
DnsProvider: pbProvider,
|
||||||
SslCert: pbCert,
|
SslCert: pbCert,
|
||||||
LatestACMETaskLog: pbTaskLog,
|
LatestACMETaskLog: pbTaskLog,
|
||||||
|
AuthType: task.AuthType,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +164,12 @@ func (this *ACMETaskService) CreateACMETask(ctx context.Context, req *pb.CreateA
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
taskId, err := models.SharedACMETaskDAO.CreateACMETask(adminId, userId, req.AcmeUserId, req.DnsProviderId, req.DnsDomain, req.Domains, req.AutoRenew)
|
|
||||||
|
if len(req.AuthType) == 0 {
|
||||||
|
req.AuthType = acme.AuthTypeDNS
|
||||||
|
}
|
||||||
|
|
||||||
|
taskId, err := models.SharedACMETaskDAO.CreateACMETask(adminId, userId, req.AuthType, req.AcmeUserId, req.DnsProviderId, req.DnsDomain, req.Domains, req.AutoRenew)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -298,5 +308,6 @@ func (this *ACMETaskService) FindEnabledACMETask(ctx context.Context, req *pb.Fi
|
|||||||
AutoRenew: task.AutoRenew == 1,
|
AutoRenew: task.AutoRenew == 1,
|
||||||
DnsProvider: pbProvider,
|
DnsProvider: pbProvider,
|
||||||
AcmeUser: pbACMEUser,
|
AcmeUser: pbACMEUser,
|
||||||
|
AuthType: task.AuthType,
|
||||||
}}, nil
|
}}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,12 @@ func (this *BaseService) ValidateAdminAndUser(ctx context.Context, reqUserId int
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 校验节点
|
||||||
|
func (this *BaseService) ValidateNode(ctx context.Context) (nodeId int64, err error) {
|
||||||
|
_, nodeId, err = rpcutils.ValidateRequest(ctx, rpcutils.UserTypeNode)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 返回成功
|
// 返回成功
|
||||||
func (this *BaseService) Success() (*pb.RPCSuccess, error) {
|
func (this *BaseService) Success() (*pb.RPCSuccess, error) {
|
||||||
return &pb.RPCSuccess{}, nil
|
return &pb.RPCSuccess{}, nil
|
||||||
|
|||||||
@@ -1067,6 +1067,11 @@ func (this *NodeService) FindEnabledNodeDNS(ctx context.Context, req *pb.FindEna
|
|||||||
return &pb.FindEnabledNodeDNSResponse{Node: nil}, nil
|
return &pb.FindEnabledNodeDNSResponse{Node: nil}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ipAddr, err := models.SharedNodeIPAddressDAO.FindFirstNodeIPAddress(int64(node.Id))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
clusterId := int64(node.ClusterId)
|
clusterId := int64(node.ClusterId)
|
||||||
clusterDNS, err := models.SharedNodeClusterDAO.FindClusterDNSInfo(clusterId)
|
clusterDNS, err := models.SharedNodeClusterDAO.FindClusterDNSInfo(clusterId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1101,11 +1106,6 @@ func (this *NodeService) FindEnabledNodeDNS(ctx context.Context, req *pb.FindEna
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ipAddr, err := models.SharedNodeIPAddressDAO.FindFirstNodeIPAddress(int64(node.Id))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &pb.FindEnabledNodeDNSResponse{
|
return &pb.FindEnabledNodeDNSResponse{
|
||||||
Node: &pb.NodeDNSInfo{
|
Node: &pb.NodeDNSInfo{
|
||||||
Id: int64(node.Id),
|
Id: int64(node.Id),
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1,6 +1,7 @@
|
|||||||
package setup
|
package setup
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/acme"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||||
"github.com/iwind/TeaGo/dbs"
|
"github.com/iwind/TeaGo/dbs"
|
||||||
"github.com/iwind/TeaGo/types"
|
"github.com/iwind/TeaGo/types"
|
||||||
@@ -16,6 +17,9 @@ var upgradeFuncs = []*upgradeVersion{
|
|||||||
{
|
{
|
||||||
"0.0.3", upgradeV0_0_3,
|
"0.0.3", upgradeV0_0_3,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"0.0.5", upgradeV0_0_5,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// 升级SQL数据
|
// 升级SQL数据
|
||||||
@@ -89,3 +93,14 @@ func upgradeV0_0_3(db *dbs.DB) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// v0.0.4
|
||||||
|
func upgradeV0_0_5(db *dbs.DB) error {
|
||||||
|
// 升级edgeACMETasks
|
||||||
|
_, err := db.Exec("UPDATE edgeACMETasks SET authType=? WHERE authType IS NULL OR LENGTH(authType)=0", acme.AuthTypeDNS)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user