mindxdl--common--web_cert_utils.go
// Copyright (c) 2021. Huawei Technologies Co., Ltd. All rights reserved.
// Package common this file define WebCertUtil
package common
import (
"crypto/tls"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"github.com/gin-gonic/gin"
"huawei.com/npu-exporter/hwlog"
"huawei.com/npu-exporter/limiter"
"huawei.com/npu-exporter/utils"
"io/ioutil"
"net/http"
"strconv"
"strings"
"time"
)
const keyLength = 4096
var webCert *WebCertUtil
// WebCertUtil WebCertUtil
type WebCertUtil struct {
*CertificateUtils
}
// NewWebCertUtil NewWebCertUtil
func NewWebCertUtil(dnsName, dirName string, overdueTime int) *WebCertUtil {
ws := &WebCertUtil{
CertificateUtils: NewCertificateUtils(dnsName, dirName, overdueTime),
}
if err := utils.MakeSureDir(ws.KeyStore); err != nil {
hwlog.RunLog.Fatal(err)
}
return ws
}
// GetWebCertUtil return webCert
func GetWebCertUtil() *WebCertUtil {
return webCert
}
// CheckCertValidityPeriod CheckCertValidityPeriod
func (ws *WebCertUtil) CheckCertValidityPeriod(interval time.Duration) {
hwlog.RunLog.Info("start cert period check...")
ticker := time.NewTicker(interval)
defer ticker.Stop()
hasTask := false
for {
_, ok := <-ticker.C
if !ok {
return
}
if hasTask {
continue
}
ws.Lock.RLock()
if ws.Cert == nil {
ws.Lock.RUnlock()
continue
}
x509Cert, err := x509.ParseCertificate(ws.Cert.Certificate[0])
if err != nil {
ws.Lock.RUnlock()
continue
}
err = utils.CheckValidityPeriodWithError(x509Cert, ws.OverdueTime)
ws.Lock.RUnlock()
if err == nil {
continue
}
hwlog.RunLog.Warn(err)
go func() {
hasTask = true
defer func() {
hasTask = false
hwlog.RunLog.Info("apply for a new certificate success")
}()
hwlog.RunLog.Info("apply for a new certificate because the certificate has expired")
if err = ws.ApplyForCertificateByRequest(); err != nil {
hwlog.RunLog.Error(err)
}
}()
}
}
// GetCaByRequest get ca by request
func (ws *WebCertUtil) GetCaByRequest() ([]byte, error) {
caByte, err := DefaultClsMgrClient.GetRootCertificate()
if err != nil {
return nil, err
}
hwlog.RunLog.Info("succeeded in getting ca certificate by request")
if err = ioutil.WriteFile(ws.CaStore, caByte, utils.RWMode); err != nil {
return nil, errors.New("write caBytes to file failed")
}
hwlog.RunLog.Info("succeeded in saving ca certificate to file")
ws.CaBytes = caByte
return caByte, nil
}
// ApplyForCertificateByRequest apply for certificate by request
func (ws *WebCertUtil) ApplyForCertificateByRequest() error {
certPem, err := DefaultClsMgrClient.ApplyForCertificatePemByte(ws.DNSName, ws.CaBytes, ws.PrivateKey)
if err != nil {
return err
}
hwlog.RunLog.Info("succeeded in getting certificate by request")
derStream := x509.MarshalPKCS1PrivateKey(ws.PrivateKey)
block := &pem.Block{
Type: RSAPrivateKey,
Bytes: derStream,
}
keyPem := pem.EncodeToMemory(block)
tlsCert, err := utils.ValidateCertPair(certPem, keyPem, false, ws.OverdueTime)
if err != nil {
return err
}
if err = ioutil.WriteFile(ws.CertStore, certPem, utils.RWMode); err != nil {
return errors.New("write certBytes to file failed ")
}
hwlog.RunLog.Info("succeeded in saving certificate to file")
ws.Lock.RLock()
defer ws.Lock.RUnlock()
ws.refreshCertStatus(tlsCert)
ws.Cert = tlsCert
return nil
}
func (ws *WebCertUtil) refreshCertStatus(tlsCert *tls.Certificate) {
// clear cert status record
ws.ClearCertificateMap()
caCert, err := utils.LoadCertsFromPEM(ws.CaBytes)
if err == nil {
// refresh ca record
err = utils.AddToCertStatusTrace(caCert)
}
if err != nil {
hwlog.RunLog.Error("prepare refresh ca info failed: " + err.Error())
}
x509Cert, err := x509.ParseCertificate(tlsCert.Certificate[0])
if err == nil {
// refresh certificate record
err = utils.AddToCertStatusTrace(x509Cert)
}
if err != nil {
hwlog.RunLog.Error("prepare refresh certificate info failed: " + err.Error())
}
hwlog.RunLog.Info("succeeded in refresh ca/cert info")
}
// SetHTTPSServer set http server config for one or two way auth
func (ws *WebCertUtil) SetHTTPSServer(s *http.Server, concurrency, maxConcurrency int,
cipherSuites []uint16, ginObj *gin.Engine) error {
tlsConfig, err := utils.NewTLSConfigV2(ws.CaBytes, *ws.Cert, cipherSuites)
if err != nil {
return err
}
tlsConfig.Certificates = nil
tlsConfig.GetCertificate = ws.GetCertificateFunc()
s.Handler = limiter.NewLimitHandler(concurrency, maxConcurrency, utils.Interceptor(ginObj, ws.CrlList), false)
s.TLSConfig = tlsConfig
return nil
}
// ReApplyCertificate reapply certificate
func (ws *WebCertUtil) ReApplyCertificate(algorithm int) error {
hwlog.RunLog.Info("prepare to reapply a new certificate")
if ws.PrivateKey == nil {
if _, err := ws.GenerateRSAPrivateKey(keyLength, algorithm); err != nil {
return err
}
}
if err := ws.ApplyForCertificateByRequest(); err != nil {
return err
}
return nil
}
// GetRequestClient get http client for request
func (ws *WebCertUtil) GetRequestClient(authMode string) (*http.Client, error) {
// https auth two way
if authMode == TwoWay {
requestClient, err := ws.GetTwoWayAuthRequestClient()
if err != nil {
return nil, err
}
return requestClient, nil
}
// https auth one way
pool, err := x509.SystemCertPool()
if err != nil {
return nil, fmt.Errorf("cannot get system trusted certificates pool: %w", err)
}
if !pool.AppendCertsFromPEM(ws.CaBytes) {
return nil, fmt.Errorf("failed to append to certificates pool")
}
c := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: pool,
},
},
}
return c, nil
}
// InitCert init cert and ca
func InitCert(sp *ServerParam) error {
ws := NewWebCertUtil(sp.DNSName, sp.DirName, sp.OverdueTime)
var reApply bool
var caBytes []byte
// load ca
_, err := ws.LoadCAOnStart(sp.AuthMode)
if err != nil && strings.Contains(err.Error(), ReApply) {
reApply = true
}
// reapply ca
if reApply {
caBytes, err = ws.GetCaByRequest()
if len(caBytes) == 0 || err != nil {
return err
}
reApply = false
}
if err != nil {
return err
}
// load cert and private key
_, err = ws.LoadCertAndKeyOnStart(sp.EncryptAlgorithm)
if err != nil && strings.Contains(err.Error(), ReApply) {
reApply = true
}
// reapply cert
if reApply {
if err = ws.ReApplyCertificate(sp.EncryptAlgorithm); err != nil {
return err
}
}
if err != nil {
return err
}
// init global WebCertUtil
webCert = ws
return nil
}
// StartServerListen StartServerListen
func StartServerListen(sp *ServerParam, engine *gin.Engine) {
s := &http.Server{
ReadTimeout: sp.ReadTimeOut * time.Second,
WriteTimeout: sp.WriteTimeOut * time.Second,
Addr: sp.IP + ":" + strconv.Itoa(sp.Port),
Handler: limiter.NewLimitHandler(sp.Concurrency, sp.MaxConcurrency, engine, false),
}
// http
if sp.EnableHTTP {
// http
hwlog.RunLog.Warn("Service started with an insecure http server enabled")
if err := s.ListenAndServe(); err != nil {
hwlog.RunLog.Error("Http server error and stopped")
}
return
}
// init web cert util
err := InitCert(sp)
if err != nil {
hwlog.RunLog.Error(err)
return
}
ParseTLSParams(sp)
wc := GetWebCertUtil()
if err = wc.SetHTTPSServer(s, sp.Concurrency, sp.MaxConcurrency, sp.CipherSuites,
engine); err != nil {
hwlog.RunLog.Error(err)
return
}
hwlog.RunLog.Info("start https server now...")
// start certificate period check
go wc.CheckCertValidityPeriod(sp.CheckCertPeriod)
if err = s.ListenAndServeTLS("", ""); err != nil {
hwlog.RunLog.Error("Https server error by: %s and stopped", err.Error())
}
}
mindxdl--common--web_cert_utils.go的更多相关文章
- Socket聊天程序——Common
写在前面: 上一篇记录了Socket聊天程序的客户端设计,为了记录的完整性,这里还是将Socket聊天的最后一个模块--Common模块记录一下.Common的设计如下: 功能说明: Common模块 ...
- angularjs 1 开发简单案例(包含common.js,service.js,controller.js,page)
common.js var app = angular.module('app', ['ngFileUpload']) .factory('SV_Common', function ($http) { ...
- Common Bugs in C Programming
There are some Common Bugs in C Programming. Most of the contents are directly from or modified from ...
- ANSI Common Lisp Practice - My Answers - Chatper - 3
Ok, Go ahead. 1 (a) (b) (c) (d) 2 注:union 在 Common Lisp 中的作用就是求两个集合的并集.但是这有一个前提,即给的两个列表已经满足集合的属性了.具体 ...
- [LeetCode] Lowest Common Ancestor of a Binary Tree 二叉树的最小共同父节点
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According ...
- [LeetCode] Lowest Common Ancestor of a Binary Search Tree 二叉搜索树的最小共同父节点
Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BS ...
- [LeetCode] Longest Common Prefix 最长共同前缀
Write a function to find the longest common prefix string amongst an array of strings. 这道题让我们求一系列字符串 ...
- 48. 二叉树两结点的最低共同父结点(3种变种情况)[Get lowest common ancestor of binary tree]
[题目] 输入二叉树中的两个结点,输出这两个结点在数中最低的共同父结点. 二叉树的结点定义如下: C++ Code 123456 struct BinaryTreeNode { int ...
- 动态规划求最长公共子序列(Longest Common Subsequence, LCS)
1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...
- 【leetcode】Longest Common Prefix
题目简述: Write a function to find the longest common prefix string amongst an array of strings. 解题思路: c ...
随机推荐
- 【短道速滑九】仿halcon中gauss_filter小半径高斯模糊优化的实现
通常,我们谈的高斯模糊,都知道其是可以行列分离的算法,现在也有着各种优化算法实现,而且其速度基本是和参数大小无关的.但是,在我们实际的应用中,我们可能会发现,有至少50%以上的场景中,我们并不需要大半 ...
- KingbaseES R6 集群禁用 root ssh 后需要修改集群为es_server 案例
案例说明: 在生产环境下,由于安全需要,主机间不允许建立root用户的ssh信任连接,这样导致KingbaseES R6 repmgr集群,通过sys_monitor.sh脚本启动集群时,节点之间不能 ...
- 如何使用memstat 插件分析内存泄漏问题
对于内存泄漏问题,如何分析并找到内存泄漏的原因是个难点.KingbaseES 提供了memstat 扩展插件用于分析内存泄漏的原因. 一.使用 memstat 插件 1.修改shared_preloa ...
- 理解virt、res、shr之间的关系(linux系统篇)
前言 想必在linux上写过程序的同学都有分析进程占用多少内存的经历,或者被问到这样的问题--你的程序在运行时占用了多少内存(物理内存)? 通常我们可以通过top命令查看进程占用了多少内存.这里我们可 ...
- Windows Powershell安装错误
今天需要更新一下VMware的 powercli.使用命令install-module -Name VMware.PowerCLI -AllowClobber但是遇到一个错误. Unable to r ...
- PHP函数小工具
PHP检测IP是否内网地址.保留地址 /** * @param string $ip 被检测的IP * @return bool 是否内网或者保留IP */ public function isInt ...
- ProxySQL 审计
1.审计日志 ProxySQL 2.0.5 引入了审计日志.此功能允许跟踪某些连接活动.要启用此功能,需要配置变量 mysql-auditlog_filename,也就是审计日志的文件名.此变量的默认 ...
- 16. 综合使用tail、forward、copy和stdout
通过一个例子进行阶段总结. 本示例使用到如下插件:in_tail, out_copy, out_stdout, out_forward, in_forward. 本示例包含两个节点: node_for ...
- 原生js如果将string类型的数进行值
原生的tring类型比较会进行隐式转换,如'100'>90 为true
- PAT (Basic Level) Practice 1020 月饼 分数 25
月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼.现给定所有种类月饼的库存量.总售价.以及市场的最大需求量,请你计算可以获得的最大收益是多少. 注意:销售时允许取出一部分库存.样 ...