github.com/vnforks/kid/v5@v5.22.1-0.20200408055009-b89d99c65676/app/security_update_check.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package app
     5  
     6  import (
     7  	"io/ioutil"
     8  	"net/http"
     9  	"net/url"
    10  	"runtime"
    11  	"strconv"
    12  
    13  	"github.com/vnforks/kid/v5/mlog"
    14  	"github.com/vnforks/kid/v5/model"
    15  	"github.com/vnforks/kid/v5/services/mailservice"
    16  	"github.com/vnforks/kid/v5/utils"
    17  )
    18  
    19  const (
    20  	SECURITY_URL           = "https://securityupdatecheck.mattermost.com"
    21  	SECURITY_UPDATE_PERIOD = 86400000 // 24 hours in milliseconds.
    22  
    23  	PROP_SECURITY_ID                = "id"
    24  	PROP_SECURITY_BUILD             = "b"
    25  	PROP_SECURITY_ENTERPRISE_READY  = "be"
    26  	PROP_SECURITY_DATABASE          = "db"
    27  	PROP_SECURITY_OS                = "os"
    28  	PROP_SECURITY_USER_COUNT        = "uc"
    29  	PROP_SECURITY_BRANCH_COUNT      = "tc"
    30  	PROP_SECURITY_ACTIVE_USER_COUNT = "auc"
    31  	PROP_SECURITY_UNIT_TESTS        = "ut"
    32  )
    33  
    34  func (s *Server) DoSecurityUpdateCheck() {
    35  	if !*s.Config().ServiceSettings.EnableSecurityFixAlert {
    36  		return
    37  	}
    38  
    39  	props, err := s.Store.System().Get()
    40  	if err != nil {
    41  		return
    42  	}
    43  
    44  	lastSecurityTime, _ := strconv.ParseInt(props[model.SYSTEM_LAST_SECURITY_TIME], 10, 0)
    45  	currentTime := model.GetMillis()
    46  
    47  	if (currentTime - lastSecurityTime) > SECURITY_UPDATE_PERIOD {
    48  		mlog.Debug("Checking for security update from Mattermost")
    49  
    50  		v := url.Values{}
    51  
    52  		v.Set(PROP_SECURITY_ID, s.diagnosticId)
    53  		v.Set(PROP_SECURITY_BUILD, model.CurrentVersion+"."+model.BuildNumber)
    54  		v.Set(PROP_SECURITY_ENTERPRISE_READY, model.BuildEnterpriseReady)
    55  		v.Set(PROP_SECURITY_DATABASE, *s.Config().SqlSettings.DriverName)
    56  		v.Set(PROP_SECURITY_OS, runtime.GOOS)
    57  
    58  		if len(props[model.SYSTEM_RAN_UNIT_TESTS]) > 0 {
    59  			v.Set(PROP_SECURITY_UNIT_TESTS, "1")
    60  		} else {
    61  			v.Set(PROP_SECURITY_UNIT_TESTS, "0")
    62  		}
    63  
    64  		systemSecurityLastTime := &model.System{Name: model.SYSTEM_LAST_SECURITY_TIME, Value: strconv.FormatInt(currentTime, 10)}
    65  		if lastSecurityTime == 0 {
    66  			s.Store.System().Save(systemSecurityLastTime)
    67  		} else {
    68  			s.Store.System().Update(systemSecurityLastTime)
    69  		}
    70  
    71  		if count, err := s.Store.User().Count(model.UserCountOptions{IncludeDeleted: true}); err == nil {
    72  			v.Set(PROP_SECURITY_USER_COUNT, strconv.FormatInt(count, 10))
    73  		}
    74  
    75  		if ucr, err := s.Store.Status().GetTotalActiveUsersCount(); err == nil {
    76  			v.Set(PROP_SECURITY_ACTIVE_USER_COUNT, strconv.FormatInt(ucr, 10))
    77  		}
    78  
    79  		if branchCount, err := s.Store.Branch().AnalyticsBranchCount(false); err == nil {
    80  			v.Set(PROP_SECURITY_BRANCH_COUNT, strconv.FormatInt(branchCount, 10))
    81  		}
    82  
    83  		res, err := http.Get(SECURITY_URL + "/security?" + v.Encode())
    84  		if err != nil {
    85  			mlog.Error("Failed to get security update information from Mattermost.")
    86  			return
    87  		}
    88  
    89  		defer res.Body.Close()
    90  
    91  		bulletins := model.SecurityBulletinsFromJson(res.Body)
    92  
    93  		for _, bulletin := range bulletins {
    94  			if bulletin.AppliesToVersion == model.CurrentVersion {
    95  				if props["SecurityBulletin_"+bulletin.Id] == "" {
    96  					users, userErr := s.Store.User().GetSystemAdminProfiles()
    97  					if userErr != nil {
    98  						mlog.Error("Failed to get system admins for security update information from Mattermost.")
    99  						return
   100  					}
   101  
   102  					resBody, err := http.Get(SECURITY_URL + "/bulletins/" + bulletin.Id)
   103  					if err != nil {
   104  						mlog.Error("Failed to get security bulletin details")
   105  						return
   106  					}
   107  
   108  					body, err := ioutil.ReadAll(resBody.Body)
   109  					res.Body.Close()
   110  					if err != nil || resBody.StatusCode != 200 {
   111  						mlog.Error("Failed to read security bulletin details")
   112  						return
   113  					}
   114  
   115  					for _, user := range users {
   116  						mlog.Info("Sending security bulletin", mlog.String("bulletin_id", bulletin.Id), mlog.String("user_email", user.Email))
   117  						license := s.License()
   118  						mailservice.SendMailUsingConfig(user.Email, utils.T("mattermost.bulletin.subject"), string(body), s.Config(), license != nil && *license.Features.Compliance)
   119  					}
   120  
   121  					bulletinSeen := &model.System{Name: "SecurityBulletin_" + bulletin.Id, Value: bulletin.Id}
   122  					s.Store.System().Save(bulletinSeen)
   123  				}
   124  			}
   125  		}
   126  	}
   127  }