github.com/haalcala/mattermost-server-change-repo@v0.0.0-20210713015153-16753fbeee5f/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/mattermost/mattermost-server/v5/mlog"
    14  	"github.com/mattermost/mattermost-server/v5/model"
    15  	"github.com/mattermost/mattermost-server/v5/services/mailservice"
    16  	"github.com/mattermost/mattermost-server/v5/utils"
    17  )
    18  
    19  const (
    20  	PropSecurityURL      = "https://securityupdatecheck.mattermost.com"
    21  	SecurityUpdatePeriod = 86400000 // 24 hours in milliseconds.
    22  
    23  	PropSecurityID              = "id"
    24  	PropSecurityBuild           = "b"
    25  	PropSecurityEnterpriseReady = "be"
    26  	PropSecurityDatabase        = "db"
    27  	PropSecurityOS              = "os"
    28  	PropSecurityUserCount       = "uc"
    29  	PropSecurityTeamCount       = "tc"
    30  	PropSecurityActiveUserCount = "auc"
    31  	PropSecurityUnitTests       = "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) > SecurityUpdatePeriod {
    48  		mlog.Debug("Checking for security update from Mattermost")
    49  
    50  		v := url.Values{}
    51  
    52  		v.Set(PropSecurityID, s.TelemetryId())
    53  		v.Set(PropSecurityBuild, model.CurrentVersion+"."+model.BuildNumber)
    54  		v.Set(PropSecurityEnterpriseReady, model.BuildEnterpriseReady)
    55  		v.Set(PropSecurityDatabase, *s.Config().SqlSettings.DriverName)
    56  		v.Set(PropSecurityOS, runtime.GOOS)
    57  
    58  		if props[model.SYSTEM_RAN_UNIT_TESTS] != "" {
    59  			v.Set(PropSecurityUnitTests, "1")
    60  		} else {
    61  			v.Set(PropSecurityUnitTests, "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(PropSecurityUserCount, strconv.FormatInt(count, 10))
    73  		}
    74  
    75  		if ucr, err := s.Store.Status().GetTotalActiveUsersCount(); err == nil {
    76  			v.Set(PropSecurityActiveUserCount, strconv.FormatInt(ucr, 10))
    77  		}
    78  
    79  		if teamCount, err := s.Store.Team().AnalyticsTeamCount(false); err == nil {
    80  			v.Set(PropSecurityTeamCount, strconv.FormatInt(teamCount, 10))
    81  		}
    82  
    83  		res, err := http.Get(PropSecurityURL + "/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(PropSecurityURL + "/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  					resBody.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  						mailConfig := s.MailServiceConfig()
   119  
   120  						mailservice.SendMailUsingConfig(user.Email, utils.T("mattermost.bulletin.subject"), string(body), mailConfig, license != nil && *license.Features.Compliance, "")
   121  					}
   122  
   123  					bulletinSeen := &model.System{Name: "SecurityBulletin_" + bulletin.Id, Value: bulletin.Id}
   124  					s.Store.System().Save(bulletinSeen)
   125  				}
   126  			}
   127  		}
   128  	}
   129  }