github.com/levb/mattermost-server@v5.3.1+incompatible/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  	"fmt"
     8  	"io/ioutil"
     9  	"net/http"
    10  	"net/url"
    11  	"runtime"
    12  	"strconv"
    13  
    14  	"github.com/mattermost/mattermost-server/mlog"
    15  	"github.com/mattermost/mattermost-server/model"
    16  	"github.com/mattermost/mattermost-server/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_TEAM_COUNT        = "tc"
    30  	PROP_SECURITY_ACTIVE_USER_COUNT = "auc"
    31  	PROP_SECURITY_UNIT_TESTS        = "ut"
    32  )
    33  
    34  func (a *App) DoSecurityUpdateCheck() {
    35  	if *a.Config().ServiceSettings.EnableSecurityFixAlert {
    36  		if result := <-a.Srv.Store.System().Get(); result.Err == nil {
    37  			props := result.Data.(model.StringMap)
    38  			lastSecurityTime, _ := strconv.ParseInt(props[model.SYSTEM_LAST_SECURITY_TIME], 10, 0)
    39  			currentTime := model.GetMillis()
    40  
    41  			if (currentTime - lastSecurityTime) > SECURITY_UPDATE_PERIOD {
    42  				mlog.Debug("Checking for security update from Mattermost")
    43  
    44  				v := url.Values{}
    45  
    46  				v.Set(PROP_SECURITY_ID, a.DiagnosticId())
    47  				v.Set(PROP_SECURITY_BUILD, model.CurrentVersion+"."+model.BuildNumber)
    48  				v.Set(PROP_SECURITY_ENTERPRISE_READY, model.BuildEnterpriseReady)
    49  				v.Set(PROP_SECURITY_DATABASE, *a.Config().SqlSettings.DriverName)
    50  				v.Set(PROP_SECURITY_OS, runtime.GOOS)
    51  
    52  				if len(props[model.SYSTEM_RAN_UNIT_TESTS]) > 0 {
    53  					v.Set(PROP_SECURITY_UNIT_TESTS, "1")
    54  				} else {
    55  					v.Set(PROP_SECURITY_UNIT_TESTS, "0")
    56  				}
    57  
    58  				systemSecurityLastTime := &model.System{Name: model.SYSTEM_LAST_SECURITY_TIME, Value: strconv.FormatInt(currentTime, 10)}
    59  				if lastSecurityTime == 0 {
    60  					<-a.Srv.Store.System().Save(systemSecurityLastTime)
    61  				} else {
    62  					<-a.Srv.Store.System().Update(systemSecurityLastTime)
    63  				}
    64  
    65  				if ucr := <-a.Srv.Store.User().GetTotalUsersCount(); ucr.Err == nil {
    66  					v.Set(PROP_SECURITY_USER_COUNT, strconv.FormatInt(ucr.Data.(int64), 10))
    67  				}
    68  
    69  				if ucr := <-a.Srv.Store.Status().GetTotalActiveUsersCount(); ucr.Err == nil {
    70  					v.Set(PROP_SECURITY_ACTIVE_USER_COUNT, strconv.FormatInt(ucr.Data.(int64), 10))
    71  				}
    72  
    73  				if tcr := <-a.Srv.Store.Team().AnalyticsTeamCount(); tcr.Err == nil {
    74  					v.Set(PROP_SECURITY_TEAM_COUNT, strconv.FormatInt(tcr.Data.(int64), 10))
    75  				}
    76  
    77  				res, err := http.Get(SECURITY_URL + "/security?" + v.Encode())
    78  				if err != nil {
    79  					mlog.Error("Failed to get security update information from Mattermost.")
    80  					return
    81  				}
    82  
    83  				bulletins := model.SecurityBulletinsFromJson(res.Body)
    84  				consumeAndClose(res)
    85  
    86  				for _, bulletin := range bulletins {
    87  					if bulletin.AppliesToVersion == model.CurrentVersion {
    88  						if props["SecurityBulletin_"+bulletin.Id] == "" {
    89  							if results := <-a.Srv.Store.User().GetSystemAdminProfiles(); results.Err != nil {
    90  								mlog.Error("Failed to get system admins for security update information from Mattermost.")
    91  								return
    92  							} else {
    93  								users := results.Data.(map[string]*model.User)
    94  
    95  								resBody, err := http.Get(SECURITY_URL + "/bulletins/" + bulletin.Id)
    96  								if err != nil {
    97  									mlog.Error("Failed to get security bulletin details")
    98  									return
    99  								}
   100  
   101  								body, err := ioutil.ReadAll(resBody.Body)
   102  								res.Body.Close()
   103  								if err != nil || resBody.StatusCode != 200 {
   104  									mlog.Error("Failed to read security bulletin details")
   105  									return
   106  								}
   107  
   108  								for _, user := range users {
   109  									mlog.Info(fmt.Sprintf("Sending security bulletin for %v to %v", bulletin.Id, user.Email))
   110  									a.SendMail(user.Email, utils.T("mattermost.bulletin.subject"), string(body))
   111  								}
   112  							}
   113  
   114  							bulletinSeen := &model.System{Name: "SecurityBulletin_" + bulletin.Id, Value: bulletin.Id}
   115  							<-a.Srv.Store.System().Save(bulletinSeen)
   116  						}
   117  					}
   118  				}
   119  			}
   120  		}
   121  	}
   122  }