fix(host,host-deployer): host-deployer add password quality check (#23875)

This commit is contained in:
wanyaoqi
2025-12-02 17:02:34 +08:00
committed by GitHub
parent 6869eca040
commit ce338f180a
18 changed files with 2984 additions and 302 deletions
+3 -1
View File
@@ -3063,10 +3063,12 @@ func (s *SBaremetalServer) SyncPartitionSize(term *ssh.Client, rootDisk *disktoo
func (s *SBaremetalServer) DoDeploy(tool *disktool.SSHPartitionTool, term *ssh.Client, data jsonutils.JSONObject, isInit bool) (jsonutils.JSONObject, error) {
publicKey := deployapi.GetKeys(data)
isRandomPassword := false
password, _ := data.GetString("password")
resetPassword := jsonutils.QueryBoolean(data, "reset_password", false)
if resetPassword && len(password) == 0 {
password = seclib.RandomPassword(12)
isRandomPassword = true
}
deployArray := make([]*deployapi.DeployContent, 0)
if data.Contains("deploys") {
@@ -3077,7 +3079,7 @@ func (s *SBaremetalServer) DoDeploy(tool *disktool.SSHPartitionTool, term *ssh.C
}
userData, _ := s.desc.GetString("user_data")
deployInfo := deployapi.NewDeployInfo(publicKey, deployArray,
password, isInit, true, o.Options.LinuxDefaultRootUser, o.Options.WindowsDefaultAdminUser, false, "",
password, isRandomPassword, isInit, true, o.Options.LinuxDefaultRootUser, o.Options.WindowsDefaultAdminUser, false, "",
false, "",
userData,
)
+1 -2
View File
@@ -179,8 +179,7 @@ func DoDeployGuestFs(rootfs fsdriver.IRootFsDriver, guestDesc *deployapi.GuestDe
return nil, errors.Wrap(err, "DeployPublicKey")
}
var secret string
if secret, err = rootfs.ChangeUserPasswd(partition, account, gid,
deployInfo.PublicKey.PublicKey, deployInfo.Password); err != nil {
if secret, err = rootfs.ChangeUserPasswd(partition, account, gid, deployInfo.PublicKey.PublicKey, deployInfo.Password, deployInfo.IsRandomPassword); err != nil {
return nil, errors.Wrap(err, "ChangeUserPasswd")
}
if len(secret) > 0 {
+1 -1
View File
@@ -78,7 +78,7 @@ func (m *sBaseAndroidRootFs) DeployPublicKey(rootfs IDiskPartition, uname string
return nil
}
func (m *sBaseAndroidRootFs) ChangeUserPasswd(part IDiskPartition, account, gid, publicKey, password string) (string, error) {
func (m *sBaseAndroidRootFs) ChangeUserPasswd(part IDiskPartition, account, gid, publicKey, password string, isRandomPassword bool) (string, error) {
return "", nil
}
+1 -1
View File
@@ -56,7 +56,7 @@ func (m *SEsxiRootFs) GetOs() string {
return "VMWare"
}
func (m *SEsxiRootFs) ChangeUserPasswd(part IDiskPartition, account, gid, publicKey, password string) (string, error) {
func (m *SEsxiRootFs) ChangeUserPasswd(part IDiskPartition, account, gid, publicKey, password string, isRandomPassword bool) (string, error) {
return utils.EncryptAESBase64(gid, "(blank)")
}
+1 -1
View File
@@ -83,7 +83,7 @@ type IRootFsDriver interface {
DeployFstabScripts(IDiskPartition, []*deployapi.Disk) error
GetLoginAccount(IDiskPartition, string, bool, bool) (string, error)
DeployPublicKey(IDiskPartition, string, *deployapi.SSHKeys) error
ChangeUserPasswd(part IDiskPartition, account, gid, publicKey, password string) (string, error)
ChangeUserPasswd(part IDiskPartition, account, gid, publicKey, password string, isRandomPassword bool) (string, error)
DeployYunionroot(rootFs IDiskPartition, pubkeys *deployapi.SSHKeys, isInit bool, enableCloudInit bool) error
EnableSerialConsole(IDiskPartition, *jsonutils.JSONDict) error
DisableSerialConsole(IDiskPartition) error
+61 -2
View File
@@ -42,6 +42,7 @@ import (
"yunion.io/x/onecloud/pkg/util/fstabutils"
"yunion.io/x/onecloud/pkg/util/netutils2"
"yunion.io/x/onecloud/pkg/util/procutils"
"yunion.io/x/onecloud/pkg/util/pwquality"
"yunion.io/x/onecloud/pkg/util/seclib2"
"yunion.io/x/onecloud/pkg/util/sysutils"
)
@@ -226,7 +227,24 @@ func (l *sLinuxRootFs) GetLoginAccount(rootFs IDiskPartition, sUser string, defa
return selUsr, nil
}
func (l *sLinuxRootFs) ChangeUserPasswd(rootFs IDiskPartition, account, gid, publicKey, password string) (string, error) {
func (l *sLinuxRootFs) checkInputPasswd(rootFs IDiskPartition, config *pwquality.Config, account, gid, publicKey, password string) string {
if config == nil {
return password
}
err := config.Validate(password, account)
if err != nil && errors.Cause(err) == pwquality.ErrPasswordTooWeak {
log.Infof("password %s too weak, try regenerate password", password)
npassword := config.GeneratePassword(seclib2.RandomPassword2)
if len(npassword) > 0 {
log.Infof("regenerate password %s", npassword)
password = npassword
}
}
return password
}
func (l *sLinuxRootFs) ChangeUserPasswd(rootFs IDiskPartition, account, gid, publicKey, password string, isRandomPassword bool) (string, error) {
var secret string
var err error
err = rootFs.Passwd(account, password, false)
@@ -1099,6 +1117,27 @@ func (d *sDebianLikeRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics
return rootFs.FilePutContents(fn, cmds.String(), false, false)
}
func (r *sDebianLikeRootFs) ChangeUserPasswd(rootFs IDiskPartition, account, gid, publicKey, password string, isRandomPassword bool) (string, error) {
if isRandomPassword {
var pwqualityConf *pwquality.Config
if rootFs.Exists("/etc/security/pwquality.conf", false) {
pwConfig, err := rootFs.FileGetContents("/etc/security/pwquality.conf", false)
if err == nil {
pwqualityConf = pwquality.ParseConfig(pwConfig)
}
}
if rootFs.Exists("/etc/pam.d/common-password", false) {
pamConfig, err := rootFs.FileGetContents("/etc/pam.d/common-password", false)
if err == nil {
pwqualityConf = pwquality.ParsePAMConfig(pamConfig, pwqualityConf)
}
}
password = r.checkInputPasswd(rootFs, pwqualityConf, account, gid, publicKey, password)
}
return r.sLinuxRootFs.ChangeUserPasswd(rootFs, account, gid, publicKey, password, isRandomPassword)
}
type SDebianRootFs struct {
*sDebianLikeRootFs
}
@@ -1394,6 +1433,26 @@ func (r *sRedhatLikeRootFs) Centos5DeployNetworkingScripts(rootFs IDiskPartition
return nil
}
func (r *sRedhatLikeRootFs) ChangeUserPasswd(rootFs IDiskPartition, account, gid, publicKey, password string, isRandomPassword bool) (string, error) {
if isRandomPassword {
var pwqualityConf *pwquality.Config
if rootFs.Exists("/etc/security/pwquality.conf", false) {
pwConfig, err := rootFs.FileGetContents("/etc/security/pwquality.conf", false)
if err == nil {
pwqualityConf = pwquality.ParseConfig(pwConfig)
}
}
if rootFs.Exists("/etc/pam.d/system-auth", false) {
pamConfig, err := rootFs.FileGetContents("/etc/pam.d/system-auth", false)
if err == nil {
pwqualityConf = pwquality.ParsePAMConfig(pamConfig, pwqualityConf)
}
}
password = r.checkInputPasswd(rootFs, pwqualityConf, account, gid, publicKey, password)
}
return r.sLinuxRootFs.ChangeUserPasswd(rootFs, account, gid, publicKey, password, isRandomPassword)
}
func getMainNic(nics []*types.SServerNic) *types.SServerNic {
for i := range nics {
if nics[i].IsDefault {
@@ -2375,7 +2434,7 @@ func (d *SCoreOsRootFs) DeployFstabScripts(rootFs IDiskPartition, disks []*deplo
return nil
}
func (d *SCoreOsRootFs) ChangeUserPasswd(rootFs IDiskPartition, account, gid, publicKey, password string) (string, error) {
func (d *SCoreOsRootFs) ChangeUserPasswd(part IDiskPartition, account, gid, publicKey, password string, isRandomPassword bool) (string, error) {
keys := []string{}
if len(publicKey) > 0 {
keys = append(keys, publicKey)
+1 -1
View File
@@ -86,7 +86,7 @@ func (m *SMacOSRootFs) addScripts(lines []string) {
m.scripts = append(m.scripts, "")
}
func (m *SMacOSRootFs) ChangeUserPasswd(part IDiskPartition, account, gid, publicKey, password string) (string, error) {
func (m *SMacOSRootFs) ChangeUserPasswd(part IDiskPartition, account, gid, publicKey, password string, isRandomPassword bool) (string, error) {
lines := []string{
fmt.Sprintf("dscl . -passwd /Users/%s %s", account, password),
fmt.Sprintf("rm -fr /Users/%s/Library/Keychains/*", account),
+1 -1
View File
@@ -444,7 +444,7 @@ func (w *SWindowsRootFs) CommitChanges(part IDiskPartition) error {
return nil
}
func (w *SWindowsRootFs) ChangeUserPasswd(part IDiskPartition, account, gid, publicKey, password string) (string, error) {
func (w *SWindowsRootFs) ChangeUserPasswd(part IDiskPartition, account, gid, publicKey, password string, isRandomPassword bool) (string, error) {
rinfo := w.GetReleaseInfo(part)
confPath := part.GetLocalPath("/windows/system32/config", true)
tool := winutils.NewWinRegTool(confPath)
+8 -31
View File
@@ -16,9 +16,9 @@ package kvmpart
import (
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"path"
"strings"
@@ -139,40 +139,17 @@ func (f *SLocalGuestFS) Zerofiles(dir string, caseInsensitive bool) error {
}
func (f *SLocalGuestFS) Passwd(account, password string, caseInsensitive bool) error {
var proc = procutils.NewCommand("chroot", f.mountPath, "passwd", account)
stdin, err := proc.StdinPipe()
if err != nil {
return err
}
defer stdin.Close()
var proc = exec.Command("chroot", f.mountPath, "passwd", account)
outb, err := proc.StdoutPipe()
if err != nil {
return err
}
defer outb.Close()
passwordInput := fmt.Sprintf("%s\n%s\n", password, password)
proc.Stdin = strings.NewReader(passwordInput)
errb, err := proc.StderrPipe()
out, err := proc.CombinedOutput()
if err != nil {
return err
return errors.Wrapf(err, "failed change passwd %s", out)
}
defer errb.Close()
if err := proc.Start(); err != nil {
return err
}
io.WriteString(stdin, fmt.Sprintf("%s\n", password))
io.WriteString(stdin, fmt.Sprintf("%s\n", password))
stdoutPut, err := ioutil.ReadAll(outb)
if err != nil {
return err
}
stderrOutPut, err := ioutil.ReadAll(errb)
if err != nil {
return err
}
log.Infof("Passwd %s %s", stdoutPut, stderrOutPut)
return proc.Wait()
log.Infof("Passwd %s", out)
return nil
}
func (f *SLocalGuestFS) Stat(usrDir string, caseInsensitive bool) os.FileInfo {
+4 -1
View File
@@ -986,10 +986,13 @@ func (m *SGuestManager) startDeploy(
return nil, errors.Wrapf(err, "unmarshal to array of deployapi.DeployContent")
}
}
isRandomPassword := false
password, _ := deployParams.Body.GetString("password")
resetPassword := jsonutils.QueryBoolean(deployParams.Body, "reset_password", false)
if resetPassword && len(password) == 0 {
password = seclib.RandomPassword2(14)
isRandomPassword = true
}
enableCloudInit := jsonutils.QueryBoolean(deployParams.Body, "enable_cloud_init", false)
loginAccount, _ := deployParams.Body.GetString("login_account")
@@ -1007,7 +1010,7 @@ func (m *SGuestManager) startDeploy(
guestInfo, err := guest.DeployFs(ctx, deployParams.UserCred,
deployapi.NewDeployInfo(
publicKey, deployArray,
password, deployParams.IsInit, false,
password, isRandomPassword, deployParams.IsInit, false,
options.HostOptions.LinuxDefaultRootUser, options.HostOptions.WindowsDefaultAdminUser,
enableCloudInit, loginAccount, deployTelegraf, telegrafConfig,
guest.GetDesc().UserData,
+257 -241
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.28.1
// protoc v3.21.2
// protoc-gen-go v1.20.0
// protoc v3.21.5
// source: deploy.proto
// protoc --version=libprotoc 3.11.3
@@ -11,6 +11,7 @@
package apis
import (
proto "github.com/golang/protobuf/proto"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
@@ -24,6 +25,10 @@ const (
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
type GuestDesc struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -668,14 +673,15 @@ type DeployInfo struct {
PublicKey *SSHKeys `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"`
Deploys []*DeployContent `protobuf:"bytes,2,rep,name=deploys,proto3" json:"deploys,omitempty"`
Password string `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"`
IsInit bool `protobuf:"varint,4,opt,name=is_init,json=isInit,proto3" json:"is_init,omitempty"`
EnableTty bool `protobuf:"varint,5,opt,name=enable_tty,json=enableTty,proto3" json:"enable_tty,omitempty"`
DefaultRootUser bool `protobuf:"varint,6,opt,name=default_root_user,json=defaultRootUser,proto3" json:"default_root_user,omitempty"`
WindowsDefaultAdminUser bool `protobuf:"varint,7,opt,name=windows_default_admin_user,json=windowsDefaultAdminUser,proto3" json:"windows_default_admin_user,omitempty"`
EnableCloudInit bool `protobuf:"varint,8,opt,name=enable_cloud_init,json=enableCloudInit,proto3" json:"enable_cloud_init,omitempty"`
LoginAccount string `protobuf:"bytes,9,opt,name=login_account,json=loginAccount,proto3" json:"login_account,omitempty"`
Telegraf *Telegraf `protobuf:"bytes,10,opt,name=telegraf,proto3" json:"telegraf,omitempty"`
UserData string `protobuf:"bytes,11,opt,name=user_data,json=userData,proto3" json:"user_data,omitempty"`
IsRandomPassword bool `protobuf:"varint,4,opt,name=is_random_password,json=isRandomPassword,proto3" json:"is_random_password,omitempty"`
IsInit bool `protobuf:"varint,5,opt,name=is_init,json=isInit,proto3" json:"is_init,omitempty"`
EnableTty bool `protobuf:"varint,6,opt,name=enable_tty,json=enableTty,proto3" json:"enable_tty,omitempty"`
DefaultRootUser bool `protobuf:"varint,7,opt,name=default_root_user,json=defaultRootUser,proto3" json:"default_root_user,omitempty"`
WindowsDefaultAdminUser bool `protobuf:"varint,8,opt,name=windows_default_admin_user,json=windowsDefaultAdminUser,proto3" json:"windows_default_admin_user,omitempty"`
EnableCloudInit bool `protobuf:"varint,9,opt,name=enable_cloud_init,json=enableCloudInit,proto3" json:"enable_cloud_init,omitempty"`
LoginAccount string `protobuf:"bytes,10,opt,name=login_account,json=loginAccount,proto3" json:"login_account,omitempty"`
Telegraf *Telegraf `protobuf:"bytes,11,opt,name=telegraf,proto3" json:"telegraf,omitempty"`
UserData string `protobuf:"bytes,12,opt,name=user_data,json=userData,proto3" json:"user_data,omitempty"`
}
func (x *DeployInfo) Reset() {
@@ -731,6 +737,13 @@ func (x *DeployInfo) GetPassword() string {
return ""
}
func (x *DeployInfo) GetIsRandomPassword() bool {
if x != nil {
return x.IsRandomPassword
}
return false
}
func (x *DeployInfo) GetIsInit() bool {
if x != nil {
return x.IsInit
@@ -2267,7 +2280,7 @@ var file_deploy_proto_rawDesc = []byte{
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61,
0x73, 0x73, 0x77, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x61, 0x73, 0x73,
0x77, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x6d, 0x72, 0x65, 0x66, 0x18, 0x05, 0x20, 0x01, 0x28,
0x09, 0x52, 0x05, 0x76, 0x6d, 0x72, 0x65, 0x66, 0x22, 0xc0, 0x03, 0x0a, 0x0a, 0x44, 0x65, 0x70,
0x09, 0x52, 0x05, 0x76, 0x6d, 0x72, 0x65, 0x66, 0x22, 0xee, 0x03, 0x0a, 0x0a, 0x44, 0x65, 0x70,
0x6c, 0x6f, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2c, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69,
0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70,
0x69, 0x73, 0x2e, 0x53, 0x53, 0x48, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c,
@@ -2276,238 +2289,241 @@ var file_deploy_proto_rawDesc = []byte{
0x70, 0x6c, 0x6f, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x64, 0x65, 0x70,
0x6c, 0x6f, 0x79, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
0x12, 0x17, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28,
0x08, 0x52, 0x06, 0x69, 0x73, 0x49, 0x6e, 0x69, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x6e, 0x61,
0x62, 0x6c, 0x65, 0x5f, 0x74, 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x65,
0x6e, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x74, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x64, 0x65, 0x66, 0x61,
0x75, 0x6c, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x18, 0x06, 0x20,
0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x6f, 0x6f, 0x74,
0x55, 0x73, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x1a, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x5f,
0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x75, 0x73,
0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77,
0x73, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x73, 0x65,
0x72, 0x12, 0x2a, 0x0a, 0x11, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6c, 0x6f, 0x75,
0x64, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x65, 0x6e,
0x61, 0x62, 0x6c, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x49, 0x6e, 0x69, 0x74, 0x12, 0x23, 0x0a,
0x0d, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x09,
0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x41, 0x63, 0x63, 0x6f, 0x75,
0x6e, 0x74, 0x12, 0x2a, 0x0a, 0x08, 0x74, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x66, 0x18, 0x0a,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x54, 0x65, 0x6c, 0x65,
0x67, 0x72, 0x61, 0x66, 0x52, 0x08, 0x74, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x66, 0x12, 0x1b,
0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0b, 0x20, 0x01, 0x28,
0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x22, 0x2f, 0x0a, 0x08, 0x54,
0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x66, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x65, 0x6c, 0x65, 0x67,
0x72, 0x61, 0x66, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c,
0x74, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x66, 0x43, 0x6f, 0x6e, 0x66, 0x22, 0xac, 0x01, 0x0a,
0x07, 0x53, 0x53, 0x48, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c,
0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75,
0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x64, 0x65, 0x6c, 0x65, 0x74,
0x65, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63,
0x4b, 0x65, 0x79, 0x12, 0x28, 0x0a, 0x10, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x70, 0x75, 0x62,
0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61,
0x64, 0x6d, 0x69, 0x6e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x2c, 0x0a,
0x12, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f,
0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x6a, 0x65,
0x63, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x22, 0x55, 0x0a, 0x0d, 0x44,
0x65, 0x70, 0x6c, 0x6f, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04,
0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68,
0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xe2, 0x01, 0x0a, 0x15,
0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x47, 0x75, 0x65, 0x73, 0x74, 0x46, 0x73, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x69, 0x73, 0x74, 0x72, 0x6f, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x69, 0x73, 0x74, 0x72, 0x6f, 0x12, 0x18, 0x0a,
0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x63, 0x68, 0x18,
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x63, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x6c,
0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c,
0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x73, 0x18, 0x05, 0x20,
0x01, 0x28, 0x09, 0x52, 0x02, 0x6f, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75,
0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e,
0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
0x6b, 0x65, 0x79, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x66, 0x5f,
0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10,
0x74, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x66, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64,
0x22, 0xaa, 0x01, 0x0a, 0x08, 0x44, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a,
0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74,
0x68, 0x12, 0x29, 0x0a, 0x10, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x5f, 0x70, 0x61, 0x73,
0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x65, 0x6e, 0x63,
0x72, 0x79, 0x70, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x25, 0x0a, 0x0e,
0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x03,
0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x46, 0x6f, 0x72,
0x6d, 0x61, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x5f, 0x61,
0x6c, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70,
0x74, 0x41, 0x6c, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18,
0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x69, 0x73, 0x6b, 0x49, 0x64, 0x22, 0xce, 0x01,
0x0a, 0x0c, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x2b,
0x0a, 0x09, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x44, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66,
0x6f, 0x52, 0x08, 0x64, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x0a, 0x0a, 0x67,
0x75, 0x65, 0x73, 0x74, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x0f, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x47, 0x75, 0x65, 0x73, 0x74, 0x44, 0x65, 0x73, 0x63,
0x52, 0x09, 0x67, 0x75, 0x65, 0x73, 0x74, 0x44, 0x65, 0x73, 0x63, 0x12, 0x31, 0x0a, 0x0b, 0x64,
0x65, 0x70, 0x6c, 0x6f, 0x79, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x49, 0x6e,
0x66, 0x6f, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e,
0x0a, 0x09, 0x76, 0x64, 0x64, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x56, 0x44, 0x44, 0x4b, 0x43, 0x6f, 0x6e,
0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x76, 0x64, 0x64, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xbd,
0x01, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x69, 0x7a, 0x65, 0x46, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d,
0x12, 0x2c, 0x0a, 0x12, 0x69, 0x73, 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x5f, 0x70, 0x61,
0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x69, 0x73,
0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x17,
0x0a, 0x07, 0x69, 0x73, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52,
0x06, 0x69, 0x73, 0x49, 0x6e, 0x69, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x6e, 0x61, 0x62, 0x6c,
0x65, 0x5f, 0x74, 0x74, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x65, 0x6e, 0x61,
0x62, 0x6c, 0x65, 0x54, 0x74, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c,
0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28,
0x08, 0x52, 0x0f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x55, 0x73,
0x65, 0x72, 0x12, 0x3b, 0x0a, 0x1a, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x5f, 0x64, 0x65,
0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x65, 0x72,
0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x44,
0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x12,
0x2a, 0x0a, 0x11, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f,
0x69, 0x6e, 0x69, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x65, 0x6e, 0x61, 0x62,
0x6c, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x49, 0x6e, 0x69, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x6c,
0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0c, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74,
0x12, 0x2a, 0x0a, 0x08, 0x74, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x66, 0x18, 0x0b, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x54, 0x65, 0x6c, 0x65, 0x67, 0x72,
0x61, 0x66, 0x52, 0x08, 0x74, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x66, 0x12, 0x1b, 0x0a, 0x09,
0x75, 0x73, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52,
0x08, 0x75, 0x73, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x22, 0x2f, 0x0a, 0x08, 0x54, 0x65, 0x6c,
0x65, 0x67, 0x72, 0x61, 0x66, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61,
0x66, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x74, 0x65,
0x6c, 0x65, 0x67, 0x72, 0x61, 0x66, 0x43, 0x6f, 0x6e, 0x66, 0x22, 0xac, 0x01, 0x0a, 0x07, 0x53,
0x53, 0x48, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63,
0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c,
0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x5f,
0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
0x52, 0x0f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65,
0x79, 0x12, 0x28, 0x0a, 0x10, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69,
0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x64, 0x6d,
0x69, 0x6e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x12, 0x70,
0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65,
0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x22, 0x55, 0x0a, 0x0d, 0x44, 0x65, 0x70,
0x6c, 0x6f, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61,
0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x18,
0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xe2, 0x01, 0x0a, 0x15, 0x44, 0x65,
0x70, 0x6c, 0x6f, 0x79, 0x47, 0x75, 0x65, 0x73, 0x74, 0x46, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x69, 0x73, 0x74, 0x72, 0x6f, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x69, 0x73, 0x74, 0x72, 0x6f, 0x12, 0x18, 0x0a, 0x07, 0x76,
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65,
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x63, 0x68, 0x18, 0x03, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x63, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x6e,
0x67, 0x75, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, 0x6e,
0x67, 0x75, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28,
0x09, 0x52, 0x02, 0x6f, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74,
0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12,
0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
0x79, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x65, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x66, 0x5f, 0x64, 0x65,
0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x74, 0x65,
0x6c, 0x65, 0x67, 0x72, 0x61, 0x66, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x22, 0xaa,
0x01, 0x0a, 0x08, 0x44, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x70,
0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12,
0x29, 0x0a, 0x10, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77,
0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x65, 0x6e, 0x63, 0x72, 0x79,
0x70, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x6e,
0x63, 0x72, 0x79, 0x70, 0x74, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0d, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x46, 0x6f, 0x72, 0x6d, 0x61,
0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x5f, 0x61, 0x6c, 0x67,
0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x41,
0x6c, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20,
0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x69, 0x73, 0x6b, 0x49, 0x64, 0x22, 0xce, 0x01, 0x0a, 0x0c,
0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x2b, 0x0a, 0x09,
0x64, 0x69, 0x73, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x0e, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x44, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52,
0x08, 0x64, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x0a, 0x0a, 0x67, 0x75, 0x65,
0x73, 0x74, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e,
0x61, 0x70, 0x69, 0x73, 0x2e, 0x47, 0x75, 0x65, 0x73, 0x74, 0x44, 0x65, 0x73, 0x63, 0x52, 0x09,
0x67, 0x75, 0x65, 0x73, 0x74, 0x44, 0x65, 0x73, 0x63, 0x12, 0x31, 0x0a, 0x0b, 0x64, 0x65, 0x70,
0x6c, 0x6f, 0x79, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10,
0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x49, 0x6e, 0x66, 0x6f,
0x52, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x0a, 0x09,
0x76, 0x64, 0x64, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x11, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x56, 0x44, 0x44, 0x4b, 0x43, 0x6f, 0x6e, 0x49, 0x6e,
0x66, 0x6f, 0x52, 0x08, 0x76, 0x64, 0x64, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xbd, 0x01, 0x0a,
0x0e, 0x52, 0x65, 0x73, 0x69, 0x7a, 0x65, 0x46, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12,
0x2b, 0x0a, 0x09, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x44, 0x69, 0x73, 0x6b, 0x49, 0x6e,
0x66, 0x6f, 0x52, 0x08, 0x64, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1e, 0x0a, 0x0a,
0x68, 0x79, 0x70, 0x65, 0x72, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
0x52, 0x0a, 0x68, 0x79, 0x70, 0x65, 0x72, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x12, 0x2e, 0x0a, 0x09,
0x76, 0x64, 0x64, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x11, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x56, 0x44, 0x44, 0x4b, 0x43, 0x6f, 0x6e, 0x49, 0x6e,
0x66, 0x6f, 0x52, 0x08, 0x76, 0x64, 0x64, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x0a, 0x0a,
0x67, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x47, 0x75, 0x65, 0x73, 0x74, 0x44, 0x65, 0x73,
0x63, 0x52, 0x09, 0x67, 0x75, 0x65, 0x73, 0x74, 0x44, 0x65, 0x73, 0x63, 0x22, 0x76, 0x0a, 0x0e,
0x46, 0x73, 0x45, 0x78, 0x74, 0x34, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x28,
0x0a, 0x0f, 0x43, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76,
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x43, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x73,
0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x12, 0x3a, 0x0a, 0x18, 0x52, 0x65, 0x73, 0x65,
0x72, 0x76, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e,
0x74, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x18, 0x52, 0x65, 0x73, 0x65,
0x72, 0x76, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e,
0x74, 0x61, 0x67, 0x65, 0x22, 0x7e, 0x0a, 0x0e, 0x46, 0x73, 0x46, 0x32, 0x66, 0x73, 0x46, 0x65,
0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x43, 0x61, 0x73, 0x65, 0x49, 0x6e,
0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52,
0x0f, 0x43, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65,
0x12, 0x42, 0x0a, 0x1c, 0x4f, 0x76, 0x65, 0x72, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f,
0x6e, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x61, 0x67, 0x65,
0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1c, 0x4f, 0x76, 0x65, 0x72, 0x70, 0x72, 0x6f, 0x76,
0x69, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e,
0x74, 0x61, 0x67, 0x65, 0x22, 0x60, 0x0a, 0x0a, 0x46, 0x73, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72,
0x65, 0x73, 0x12, 0x28, 0x0a, 0x04, 0x65, 0x78, 0x74, 0x34, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x46, 0x73, 0x45, 0x78, 0x74, 0x34, 0x46, 0x65,
0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x04, 0x65, 0x78, 0x74, 0x34, 0x12, 0x28, 0x0a, 0x04,
0x66, 0x32, 0x66, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69,
0x73, 0x2e, 0x46, 0x73, 0x46, 0x32, 0x66, 0x73, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73,
0x52, 0x04, 0x66, 0x32, 0x66, 0x73, 0x22, 0xa1, 0x01, 0x0a, 0x0e, 0x46, 0x6f, 0x72, 0x6d, 0x61,
0x74, 0x46, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x2b, 0x0a, 0x09, 0x64, 0x69, 0x73,
0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61,
0x70, 0x69, 0x73, 0x2e, 0x44, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x64, 0x69,
0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x73, 0x5f, 0x66, 0x6f, 0x72,
0x6d, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x73, 0x46, 0x6f, 0x72,
0x6d, 0x61, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x31, 0x0a, 0x0b, 0x66, 0x73, 0x5f, 0x66, 0x65,
0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61,
0x70, 0x69, 0x73, 0x2e, 0x46, 0x73, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x0a,
0x66, 0x73, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x22, 0x6f, 0x0a, 0x0b, 0x52, 0x65,
0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x69, 0x73,
0x74, 0x72, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x69, 0x73, 0x74, 0x72,
0x6f, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x61,
0x72, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x63, 0x68, 0x12,
0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28,
0x09, 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x22, 0x5d, 0x0a, 0x12, 0x53,
0x61, 0x76, 0x65, 0x54, 0x6f, 0x47, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d,
0x73, 0x12, 0x2b, 0x0a, 0x09, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x44, 0x69, 0x73, 0x6b,
0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x64, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1e,
0x0a, 0x0a, 0x68, 0x79, 0x70, 0x65, 0x72, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0a, 0x68, 0x79, 0x70, 0x65, 0x72, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x12, 0x2e,
0x0a, 0x09, 0x76, 0x64, 0x64, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x56, 0x44, 0x44, 0x4b, 0x43, 0x6f, 0x6e,
0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x76, 0x64, 0x64, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e,
0x0a, 0x0a, 0x67, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x18, 0x04, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x47, 0x75, 0x65, 0x73, 0x74, 0x44,
0x65, 0x73, 0x63, 0x52, 0x09, 0x67, 0x75, 0x65, 0x73, 0x74, 0x44, 0x65, 0x73, 0x63, 0x22, 0x76,
0x0a, 0x0e, 0x46, 0x73, 0x45, 0x78, 0x74, 0x34, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73,
0x12, 0x28, 0x0a, 0x0f, 0x43, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74,
0x69, 0x76, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x43, 0x61, 0x73, 0x65, 0x49,
0x6e, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x12, 0x3a, 0x0a, 0x18, 0x52, 0x65,
0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x50, 0x65, 0x72, 0x63,
0x65, 0x6e, 0x74, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x18, 0x52, 0x65,
0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x50, 0x65, 0x72, 0x63,
0x65, 0x6e, 0x74, 0x61, 0x67, 0x65, 0x22, 0x7e, 0x0a, 0x0e, 0x46, 0x73, 0x46, 0x32, 0x66, 0x73,
0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x43, 0x61, 0x73, 0x65,
0x49, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
0x08, 0x52, 0x0f, 0x43, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69,
0x76, 0x65, 0x12, 0x42, 0x0a, 0x1c, 0x4f, 0x76, 0x65, 0x72, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73,
0x69, 0x6f, 0x6e, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x61,
0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1c, 0x4f, 0x76, 0x65, 0x72, 0x70, 0x72,
0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x50, 0x65, 0x72, 0x63,
0x65, 0x6e, 0x74, 0x61, 0x67, 0x65, 0x22, 0x60, 0x0a, 0x0a, 0x46, 0x73, 0x46, 0x65, 0x61, 0x74,
0x75, 0x72, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x04, 0x65, 0x78, 0x74, 0x34, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x46, 0x73, 0x45, 0x78, 0x74, 0x34,
0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x04, 0x65, 0x78, 0x74, 0x34, 0x12, 0x28,
0x0a, 0x04, 0x66, 0x32, 0x66, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61,
0x70, 0x69, 0x73, 0x2e, 0x46, 0x73, 0x46, 0x32, 0x66, 0x73, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72,
0x65, 0x73, 0x52, 0x04, 0x66, 0x32, 0x66, 0x73, 0x22, 0xa1, 0x01, 0x0a, 0x0e, 0x46, 0x6f, 0x72,
0x6d, 0x61, 0x74, 0x46, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x2b, 0x0a, 0x09, 0x64,
0x69, 0x73, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e,
0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x44, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08,
0x64, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x73, 0x5f, 0x66,
0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x73, 0x46,
0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x31, 0x0a, 0x0b, 0x66, 0x73, 0x5f,
0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10,
0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x46, 0x73, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73,
0x52, 0x0a, 0x66, 0x73, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x22, 0x6f, 0x0a, 0x0b,
0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x64,
0x69, 0x73, 0x74, 0x72, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x69, 0x73,
0x74, 0x72, 0x6f, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a,
0x04, 0x61, 0x72, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x63,
0x68, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20,
0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x22, 0x5d, 0x0a,
0x12, 0x53, 0x61, 0x76, 0x65, 0x54, 0x6f, 0x47, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x50, 0x61, 0x72,
0x61, 0x6d, 0x73, 0x12, 0x2b, 0x0a, 0x09, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x44, 0x69,
0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x64, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f,
0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01,
0x28, 0x08, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x22, 0x65, 0x0a, 0x14,
0x53, 0x61, 0x76, 0x65, 0x54, 0x6f, 0x47, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x6f, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x34, 0x0a,
0x0c, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61,
0x73, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49,
0x6e, 0x66, 0x6f, 0x22, 0x43, 0x0a, 0x14, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x49, 0x6d, 0x61, 0x67,
0x65, 0x49, 0x6e, 0x66, 0x6f, 0x50, 0x72, 0x61, 0x6d, 0x61, 0x73, 0x12, 0x2b, 0x0a, 0x09, 0x64,
0x69, 0x73, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e,
0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x44, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08,
0x64, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xda, 0x02, 0x0a, 0x09, 0x49, 0x6d, 0x61,
0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2a, 0x0a, 0x07, 0x6f, 0x73, 0x5f, 0x69, 0x6e, 0x66,
0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x52,
0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x6f, 0x73, 0x49, 0x6e,
0x66, 0x6f, 0x12, 0x17, 0x0a, 0x07, 0x6f, 0x73, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x69,
0x73, 0x5f, 0x75, 0x65, 0x66, 0x69, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03,
0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x69, 0x73, 0x55, 0x65, 0x66, 0x69, 0x53, 0x75, 0x70, 0x70,
0x6f, 0x72, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x69, 0x73, 0x5f, 0x6c, 0x76, 0x6d, 0x5f, 0x70, 0x61,
0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x69,
0x73, 0x4c, 0x76, 0x6d, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a,
0x0b, 0x69, 0x73, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x05, 0x20, 0x01,
0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x52, 0x65, 0x61, 0x64, 0x6f, 0x6e, 0x6c, 0x79, 0x12, 0x36,
0x0a, 0x17, 0x70, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69,
0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52,
0x15, 0x70, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69,
0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x35, 0x0a, 0x17, 0x69, 0x73, 0x5f, 0x69, 0x6e, 0x73,
0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x69, 0x6e, 0x69,
0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x69, 0x73, 0x49, 0x6e, 0x73, 0x74, 0x61,
0x6c, 0x6c, 0x65, 0x64, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x49, 0x6e, 0x69, 0x74, 0x12, 0x26, 0x0a,
0x0f, 0x69, 0x73, 0x5f, 0x62, 0x69, 0x6f, 0x73, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74,
0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x69, 0x73, 0x42, 0x69, 0x6f, 0x73, 0x53, 0x75,
0x70, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x2b, 0x0a, 0x0c, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73,
0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x70, 0x61,
0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x69, 0x73, 0x6b, 0x50, 0x61,
0x74, 0x68, 0x22, 0x7d, 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x45, 0x73, 0x78,
0x69, 0x44, 0x69, 0x73, 0x6b, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x2e, 0x0a, 0x09,
0x76, 0x64, 0x64, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x11, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x56, 0x44, 0x44, 0x4b, 0x43, 0x6f, 0x6e, 0x49, 0x6e,
0x66, 0x6f, 0x52, 0x08, 0x76, 0x64, 0x64, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x33, 0x0a, 0x0b,
0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73,
0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66,
0x6f, 0x22, 0x43, 0x0a, 0x17, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x73, 0x43, 0x6f,
0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x28, 0x0a, 0x05,
0x64, 0x69, 0x73, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70,
0x69, 0x73, 0x2e, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52,
0x05, 0x64, 0x69, 0x73, 0x6b, 0x73, 0x22, 0x67, 0x0a, 0x0b, 0x42, 0x6f, 0x6f, 0x74, 0x44, 0x65,
0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x42, 0x6f, 0x6f, 0x74, 0x4f, 0x72, 0x64,
0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x42, 0x6f, 0x6f, 0x74, 0x4f, 0x72,
0x64, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x44, 0x65, 0x76, 0x54, 0x79, 0x70, 0x65, 0x18, 0x02,
0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x44, 0x65, 0x76, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a,
0x0b, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01,
0x28, 0x05, 0x52, 0x0b, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x22,
0x60, 0x0a, 0x13, 0x4f, 0x76, 0x6d, 0x66, 0x42, 0x6f, 0x6f, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72,
0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x4f, 0x76, 0x6d, 0x66, 0x56, 0x61,
0x72, 0x73, 0x50, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x4f, 0x76,
0x6d, 0x66, 0x56, 0x61, 0x72, 0x73, 0x50, 0x61, 0x74, 0x68, 0x12, 0x25, 0x0a, 0x04, 0x64, 0x65,
0x76, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e,
0x42, 0x6f, 0x6f, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x04, 0x64, 0x65, 0x76,
0x73, 0x32, 0x82, 0x04, 0x0a, 0x0b, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x41, 0x67, 0x65, 0x6e,
0x74, 0x12, 0x40, 0x0a, 0x0d, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x47, 0x75, 0x65, 0x73, 0x74,
0x46, 0x73, 0x12, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79,
0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x44, 0x65,
0x70, 0x6c, 0x6f, 0x79, 0x47, 0x75, 0x65, 0x73, 0x74, 0x46, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x69, 0x7a, 0x65, 0x46, 0x73, 0x12,
0x14, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x69, 0x7a, 0x65, 0x46, 0x73, 0x50,
0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x45, 0x6d, 0x70,
0x74, 0x79, 0x12, 0x2d, 0x0a, 0x08, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x46, 0x73, 0x12, 0x14,
0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x46, 0x73, 0x50, 0x61,
0x72, 0x61, 0x6d, 0x73, 0x1a, 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74,
0x79, 0x12, 0x44, 0x0a, 0x0c, 0x53, 0x61, 0x76, 0x65, 0x54, 0x6f, 0x47, 0x6c, 0x61, 0x6e, 0x63,
0x65, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x54, 0x6f, 0x47,
0x6c, 0x61, 0x6e, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1a, 0x2e, 0x61, 0x70,
0x69, 0x73, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x54, 0x6f, 0x47, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x62, 0x65,
0x49, 0x6d, 0x61, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x73,
0x2e, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x50,
0x72, 0x61, 0x6d, 0x61, 0x73, 0x1a, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x49, 0x6d, 0x61,
0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x4f, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
0x74, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x73, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69,
0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73,
0x6b, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e,
0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x73, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x41, 0x0a, 0x13, 0x44, 0x69, 0x73, 0x63, 0x6f,
0x6e, 0x6e, 0x65, 0x63, 0x74, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x73, 0x12, 0x1d,
0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x73, 0x43,
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0x0b, 0x2e,
0x61, 0x70, 0x69, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3a, 0x0a, 0x10, 0x53, 0x65,
0x74, 0x4f, 0x76, 0x6d, 0x66, 0x42, 0x6f, 0x6f, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x19,
0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x4f, 0x76, 0x6d, 0x66, 0x42, 0x6f, 0x6f, 0x74, 0x4f, 0x72,
0x64, 0x65, 0x72, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x73,
0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x34, 0x5a, 0x32, 0x79, 0x75, 0x6e, 0x69, 0x6f, 0x6e,
0x2e, 0x69, 0x6f, 0x2f, 0x78, 0x2f, 0x6f, 0x6e, 0x65, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x70,
0x6b, 0x67, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x6d, 0x61, 0x6e, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x64,
0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x62, 0x06, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x33,
0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x64, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1a,
0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08,
0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x22, 0x65, 0x0a, 0x14, 0x53, 0x61,
0x76, 0x65, 0x54, 0x6f, 0x47, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x6f, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x34, 0x0a, 0x0c, 0x72,
0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65,
0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x66,
0x6f, 0x22, 0x43, 0x0a, 0x14, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x49,
0x6e, 0x66, 0x6f, 0x50, 0x72, 0x61, 0x6d, 0x61, 0x73, 0x12, 0x2b, 0x0a, 0x09, 0x64, 0x69, 0x73,
0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61,
0x70, 0x69, 0x73, 0x2e, 0x44, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x64, 0x69,
0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xda, 0x02, 0x0a, 0x09, 0x49, 0x6d, 0x61, 0x67, 0x65,
0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2a, 0x0a, 0x07, 0x6f, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x52, 0x65, 0x6c,
0x65, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x6f, 0x73, 0x49, 0x6e, 0x66, 0x6f,
0x12, 0x17, 0x0a, 0x07, 0x6f, 0x73, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x52, 0x06, 0x6f, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x69, 0x73, 0x5f,
0x75, 0x65, 0x66, 0x69, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01,
0x28, 0x08, 0x52, 0x0d, 0x69, 0x73, 0x55, 0x65, 0x66, 0x69, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72,
0x74, 0x12, 0x28, 0x0a, 0x10, 0x69, 0x73, 0x5f, 0x6c, 0x76, 0x6d, 0x5f, 0x70, 0x61, 0x72, 0x74,
0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x69, 0x73, 0x4c,
0x76, 0x6d, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x69,
0x73, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08,
0x52, 0x0a, 0x69, 0x73, 0x52, 0x65, 0x61, 0x64, 0x6f, 0x6e, 0x6c, 0x79, 0x12, 0x36, 0x0a, 0x17,
0x70, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69,
0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x70,
0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e,
0x54, 0x79, 0x70, 0x65, 0x12, 0x35, 0x0a, 0x17, 0x69, 0x73, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61,
0x6c, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x18,
0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x69, 0x73, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
0x65, 0x64, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x49, 0x6e, 0x69, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x69,
0x73, 0x5f, 0x62, 0x69, 0x6f, 0x73, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x08,
0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x69, 0x73, 0x42, 0x69, 0x6f, 0x73, 0x53, 0x75, 0x70, 0x70,
0x6f, 0x72, 0x74, 0x22, 0x2b, 0x0a, 0x0c, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x49,
0x6e, 0x66, 0x6f, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x70, 0x61, 0x74, 0x68,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x69, 0x73, 0x6b, 0x50, 0x61, 0x74, 0x68,
0x22, 0x7d, 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x45, 0x73, 0x78, 0x69, 0x44,
0x69, 0x73, 0x6b, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x2e, 0x0a, 0x09, 0x76, 0x64,
0x64, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e,
0x61, 0x70, 0x69, 0x73, 0x2e, 0x56, 0x44, 0x44, 0x4b, 0x43, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f,
0x52, 0x08, 0x76, 0x64, 0x64, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x33, 0x0a, 0x0b, 0x61, 0x63,
0x63, 0x65, 0x73, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x12, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x49,
0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x22,
0x43, 0x0a, 0x17, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x73, 0x43, 0x6f, 0x6e, 0x6e,
0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x28, 0x0a, 0x05, 0x64, 0x69,
0x73, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x73,
0x2e, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x64,
0x69, 0x73, 0x6b, 0x73, 0x22, 0x67, 0x0a, 0x0b, 0x42, 0x6f, 0x6f, 0x74, 0x44, 0x65, 0x76, 0x69,
0x63, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x42, 0x6f, 0x6f, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72,
0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x42, 0x6f, 0x6f, 0x74, 0x4f, 0x72, 0x64, 0x65,
0x72, 0x12, 0x18, 0x0a, 0x07, 0x44, 0x65, 0x76, 0x54, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x05, 0x52, 0x07, 0x44, 0x65, 0x76, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x41,
0x74, 0x74, 0x61, 0x63, 0x68, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05,
0x52, 0x0b, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x22, 0x60, 0x0a,
0x13, 0x4f, 0x76, 0x6d, 0x66, 0x42, 0x6f, 0x6f, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x50, 0x61,
0x72, 0x61, 0x6d, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x4f, 0x76, 0x6d, 0x66, 0x56, 0x61, 0x72, 0x73,
0x50, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x4f, 0x76, 0x6d, 0x66,
0x56, 0x61, 0x72, 0x73, 0x50, 0x61, 0x74, 0x68, 0x12, 0x25, 0x0a, 0x04, 0x64, 0x65, 0x76, 0x73,
0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x42, 0x6f,
0x6f, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x04, 0x64, 0x65, 0x76, 0x73, 0x32,
0x82, 0x04, 0x0a, 0x0b, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12,
0x40, 0x0a, 0x0d, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x47, 0x75, 0x65, 0x73, 0x74, 0x46, 0x73,
0x12, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x50, 0x61,
0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x44, 0x65, 0x70, 0x6c,
0x6f, 0x79, 0x47, 0x75, 0x65, 0x73, 0x74, 0x46, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x2d, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x69, 0x7a, 0x65, 0x46, 0x73, 0x12, 0x14, 0x2e,
0x61, 0x70, 0x69, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x69, 0x7a, 0x65, 0x46, 0x73, 0x50, 0x61, 0x72,
0x61, 0x6d, 0x73, 0x1a, 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79,
0x12, 0x2d, 0x0a, 0x08, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x46, 0x73, 0x12, 0x14, 0x2e, 0x61,
0x70, 0x69, 0x73, 0x2e, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x46, 0x73, 0x50, 0x61, 0x72, 0x61,
0x6d, 0x73, 0x1a, 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12,
0x44, 0x0a, 0x0c, 0x53, 0x61, 0x76, 0x65, 0x54, 0x6f, 0x47, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12,
0x18, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x54, 0x6f, 0x47, 0x6c, 0x61,
0x6e, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x73,
0x2e, 0x53, 0x61, 0x76, 0x65, 0x54, 0x6f, 0x47, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x49, 0x6d,
0x61, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x50,
0x72, 0x6f, 0x62, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x50, 0x72, 0x61,
0x6d, 0x61, 0x73, 0x1a, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65,
0x49, 0x6e, 0x66, 0x6f, 0x12, 0x4f, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x45,
0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x73, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e,
0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x73,
0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x45, 0x73,
0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x73, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x41, 0x0a, 0x13, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e,
0x65, 0x63, 0x74, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x73, 0x12, 0x1d, 0x2e, 0x61,
0x70, 0x69, 0x73, 0x2e, 0x45, 0x73, 0x78, 0x69, 0x44, 0x69, 0x73, 0x6b, 0x73, 0x43, 0x6f, 0x6e,
0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0x0b, 0x2e, 0x61, 0x70,
0x69, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3a, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x4f,
0x76, 0x6d, 0x66, 0x42, 0x6f, 0x6f, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x19, 0x2e, 0x61,
0x70, 0x69, 0x73, 0x2e, 0x4f, 0x76, 0x6d, 0x66, 0x42, 0x6f, 0x6f, 0x74, 0x4f, 0x72, 0x64, 0x65,
0x72, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x45,
0x6d, 0x70, 0x74, 0x79, 0x42, 0x34, 0x5a, 0x32, 0x79, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x2e, 0x69,
0x6f, 0x2f, 0x78, 0x2f, 0x6f, 0x6e, 0x65, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x70, 0x6b, 0x67,
0x2f, 0x68, 0x6f, 0x73, 0x74, 0x6d, 0x61, 0x6e, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x64, 0x65, 0x70,
0x6c, 0x6f, 0x79, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
}
var (
+9 -8
View File
@@ -85,14 +85,15 @@ message DeployInfo {
SSHKeys public_key = 1;
repeated DeployContent deploys = 2;
string password = 3;
bool is_init = 4;
bool enable_tty = 5;
bool default_root_user = 6;
bool windows_default_admin_user = 7;
bool enable_cloud_init = 8;
string login_account = 9;
Telegraf telegraf = 10;
string user_data = 11;
bool is_random_password =4;
bool is_init = 5;
bool enable_tty = 6;
bool default_root_user = 7;
bool windows_default_admin_user = 8;
bool enable_cloud_init = 9;
string login_account = 10;
Telegraf telegraf = 11;
string user_data = 12;
}
message Telegraf {
@@ -1,8 +1,4 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.2.0
// - protoc v3.21.2
// source: deploy.proto
package apis
@@ -15,7 +11,6 @@ import (
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// DeployAgentClient is the client API for DeployAgent service.
@@ -165,7 +160,7 @@ type UnsafeDeployAgentServer interface {
}
func RegisterDeployAgentServer(s grpc.ServiceRegistrar, srv DeployAgentServer) {
s.RegisterService(&DeployAgent_ServiceDesc, srv)
s.RegisterService(&_DeployAgent_serviceDesc, srv)
}
func _DeployAgent_DeployGuestFs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
@@ -312,10 +307,7 @@ func _DeployAgent_SetOvmfBootOrder_Handler(srv interface{}, ctx context.Context,
return interceptor(ctx, in, info, handler)
}
// DeployAgent_ServiceDesc is the grpc.ServiceDesc for DeployAgent service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var DeployAgent_ServiceDesc = grpc.ServiceDesc{
var _DeployAgent_serviceDesc = grpc.ServiceDesc{
ServiceName: "apis.DeployAgent",
HandlerType: (*DeployAgentServer)(nil),
Methods: []grpc.MethodDesc{
+2
View File
@@ -32,6 +32,7 @@ func NewDeployInfo(
publicKey *SSHKeys,
deploys []*DeployContent,
password string,
isRandomPassword,
isInit bool,
enableTty bool,
defaultRootUser bool,
@@ -46,6 +47,7 @@ func NewDeployInfo(
PublicKey: publicKey,
Deploys: deploys,
Password: password,
IsRandomPassword: isRandomPassword,
IsInit: isInit,
EnableTty: enableTty,
DefaultRootUser: defaultRootUser,
+3 -1
View File
@@ -336,10 +336,12 @@ func (as *SAgentStorage) AgentDeployGuest(ctx context.Context, data interface{})
}
}
isRandomPassword := false
passwd, _ := dataDict.GetString("password")
resetPassword := jsonutils.QueryBoolean(dataDict, "reset_password", false)
if resetPassword && len(passwd) == 0 {
passwd = seclib.RandomPassword(12)
isRandomPassword = true
}
enableCloudInit := jsonutils.QueryBoolean(dataDict, "enable_cloud_init", false)
@@ -350,7 +352,7 @@ func (as *SAgentStorage) AgentDeployGuest(ctx context.Context, data interface{})
return nil, errors.Errorf("missing telegraf_conf")
}
deployInfo := deployapi.NewDeployInfo(&key, deployArray, passwd, init, false,
deployInfo := deployapi.NewDeployInfo(&key, deployArray, passwd, isRandomPassword, init, false,
options.HostOptions.LinuxDefaultRootUser, options.HostOptions.WindowsDefaultAdminUser,
enableCloudInit, loginAccount, deployTelegraf, telegrafConfig,
desc.UserData,
+15
View File
@@ -0,0 +1,15 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package pwquality // import "yunion.io/x/onecloud/pkg/util/pwquality"
+634
View File
@@ -0,0 +1,634 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package pwquality
import (
"strconv"
"strings"
"unicode"
"yunion.io/x/pkg/errors"
)
// ErrPasswordTooWeak 表示密码强度不符合要求的统一错误
var ErrPasswordTooWeak = errors.Error("password too weak")
// Config 存储 pwquality 配置
type Config struct {
Minlen int // 最小长度
Dcredit int // 数字字符信用值(负数表示至少需要多少个字符,正数表示每个字符可减少的长度要求)
Ucredit int // 大写字母信用值
Lcredit int // 小写字母信用值
Ocredit int // 特殊字符信用值
Minclass int // 最小字符类数量(数字、大写、小写、特殊)
Maxrepeat int // 最大重复字符数(0 表示不限制)
Maxclassrepeat int // 最大同类字符重复数(0 表示不限制)
Maxsequence int // 最大连续字符序列长度(0 表示不限制)
// Enforcing 是否强制执行密码策略(1=强制执行,0=仅警告,默认1)
// 注意:此参数在 libpwquality 1.2.0+ 版本中支持,较老的系统可能不支持
// 如果系统不支持,配置文件中不会出现此参数,将使用默认值 1(强制执行)
Enforcing int
// EnforceForRoot 是否对 root 用户强制执行密码策略(1=强制执行,0=不强制,默认0)
// 注意:此参数在 libpwquality 1.2.0+ 版本中支持,较老的系统可能不支持
// 在配置文件中,可能以两种形式出现:
// 1. enforce_for_root = 1key=value 形式)
// 2. enforce_for_root(独立标志形式,无等号,表示启用)
// 如果系统不支持,配置文件中不会出现此参数,将使用默认值 0(不对 root 强制执行)
EnforceForRoot int
Usercheck int // 是否检查密码中包含用户名(1=检查,0=不检查,默认0)
// 以下配置项在 chroot 环境中可能不适用,暂不实现
// Gecoscheck int // 是否检查密码中包含用户的 GECOS 信息
// Dictcheck int // 是否检查密码是否包含字典中的单词(需要字典文件)
// Dictpath string // 字典文件路径
}
// HasAnyPolicy 检查配置是否有任何非默认的密码策略设置
// 用于判断配置是否有效(即是否包含任何密码强度要求)
func (c *Config) HasAnyPolicy() bool {
if c == nil {
return false
}
return c.Minlen > 0 || c.Dcredit != 0 || c.Ucredit != 0 ||
c.Lcredit != 0 || c.Ocredit != 0 || c.Minclass > 0 ||
c.Maxrepeat > 0 || c.Maxclassrepeat > 0 || c.Maxsequence > 0
}
// IsEnforcing 检查密码策略是否强制执行
// 如果 enforcing=0,密码策略不会强制执行(只是警告)
func (c *Config) IsEnforcing() bool {
if c == nil {
return true // 默认强制执行
}
// enforcing=1 表示强制执行,enforcing=0 表示仅警告
// 默认值为 1(强制执行)
return c.Enforcing != 0
}
// IsEnforcingForRoot 检查是否对 root 用户强制执行密码策略
func (c *Config) IsEnforcingForRoot() bool {
if c == nil {
return false // 默认不对 root 强制执行
}
// enforce_for_root=1 表示对 root 强制执行,enforce_for_root=0 表示不强制
return c.EnforceForRoot == 1
}
// ParseConfig 解析 /etc/security/pwquality.conf 配置文件内容
//
// 兼容性说明:
// - enforcing 和 enforce_for_root 参数在 libpwquality 1.2.0+ 版本中支持
// - 较老的系统(如 RHEL 6 之前)可能不支持这些参数
// - enforce_for_root 可能以两种形式出现:
// 1. enforce_for_root = 1key=value 形式)
// 2. enforce_for_root(独立标志形式,无等号,表示启用)
//
// - 如果配置文件中不存在这些参数,将使用默认值:
// - Enforcing: 1(默认强制执行)
// - EnforceForRoot: 0(默认不对 root 强制执行)
func ParseConfig(content []byte) *Config {
config := &Config{
Minlen: 0, // 默认值
Dcredit: 0, // 默认值
Ucredit: 0, // 默认值
Lcredit: 0, // 默认值
Ocredit: 0, // 默认值
Minclass: 0, // 默认值
Maxrepeat: 0, // 默认值(0 表示不限制)
Maxclassrepeat: 0, // 默认值(0 表示不限制)
Maxsequence: 0, // 默认值(0 表示不限制)
Enforcing: 1, // 默认值(1 表示强制执行)
EnforceForRoot: 0, // 默认值(0 表示不对 root 强制执行)
Usercheck: 0, // 默认值(0 表示不检查用户名)
}
lines := strings.Split(string(content), "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
// 跳过注释和空行
if len(line) == 0 || strings.HasPrefix(line, "#") {
continue
}
// 检查是否是 key = value 格式
if strings.Contains(line, "=") {
// 解析 key = value 格式
parts := strings.SplitN(line, "=", 2)
if len(parts) != 2 {
continue
}
key := strings.TrimSpace(parts[0])
value := strings.TrimSpace(parts[1])
switch key {
case "minlen":
if v, err := strconv.Atoi(value); err == nil {
config.Minlen = v
}
case "dcredit":
if v, err := strconv.Atoi(value); err == nil {
config.Dcredit = v
}
case "ucredit":
if v, err := strconv.Atoi(value); err == nil {
config.Ucredit = v
}
case "lcredit":
if v, err := strconv.Atoi(value); err == nil {
config.Lcredit = v
}
case "ocredit":
if v, err := strconv.Atoi(value); err == nil {
config.Ocredit = v
}
case "minclass":
if v, err := strconv.Atoi(value); err == nil {
config.Minclass = v
}
case "maxrepeat":
if v, err := strconv.Atoi(value); err == nil {
config.Maxrepeat = v
}
case "maxclassrepeat":
if v, err := strconv.Atoi(value); err == nil {
config.Maxclassrepeat = v
}
case "maxsequence":
if v, err := strconv.Atoi(value); err == nil {
config.Maxsequence = v
}
case "enforcing":
if v, err := strconv.Atoi(value); err == nil {
config.Enforcing = v
}
case "enforce_for_root":
if v, err := strconv.Atoi(value); err == nil {
config.EnforceForRoot = v
}
case "usercheck":
if v, err := strconv.Atoi(value); err == nil {
config.Usercheck = v
}
}
} else {
// 处理独立标志(无值的参数)
// 例如:enforce_for_root(表示对 root 强制执行密码策略)
key := strings.TrimSpace(line)
switch key {
case "enforce_for_root":
// 如果以独立标志形式出现,设置为 1(强制执行)
config.EnforceForRoot = 1
}
}
}
return config
}
// Validate 根据 pwquality 配置校验密码强度
// username 为用户名,用于检查密码中是否包含用户名(如果启用了 usercheck)
// 参考 libpwquality 的实现逻辑
func (c *Config) Validate(password string, username string) error {
if !c.HasAnyPolicy() {
return nil
}
// 如果 enforcing=0,密码策略不会强制执行(只是警告),直接返回
//if username != "root" && !c.IsEnforcing() {
// return nil
//}
// 如果用户是 root 且 enforce_for_root=0,不对 root 强制执行密码策略
//if username == "root" && !c.IsEnforcingForRoot() {
// return nil
//}
// 统计各类字符数量
var digits, uppers, lowers, others int
for _, r := range password {
if unicode.IsDigit(r) {
digits++
} else if unicode.IsUpper(r) {
uppers++
} else if unicode.IsLower(r) {
lowers++
} else {
others++
}
}
// 处理 credit 值
// 根据 libpwquality 的文档:
// - 负数(如 -1):表示至少需要多少个字符(常用)
// - 正数(如 1):表示每个字符可以减少多少长度要求(较少用)
// - 0:不要求
if c.Dcredit < 0 {
// 负数:至少需要这么多数字字符
required := -c.Dcredit
if digits < required {
return errors.Wrapf(ErrPasswordTooWeak, "password requires at least %d digit(s), got %d", required, digits)
}
} else if c.Dcredit > 0 {
// 正数:每个数字字符可以减少多少长度要求(较少使用)
// 这里我们简化处理,只检查是否有数字
if digits == 0 {
return errors.Wrapf(ErrPasswordTooWeak, "password should contain at least one digit")
}
}
if c.Ucredit < 0 {
required := -c.Ucredit
if uppers < required {
return errors.Wrapf(ErrPasswordTooWeak, "password requires at least %d uppercase letter(s), got %d", required, uppers)
}
} else if c.Ucredit > 0 {
if uppers == 0 {
return errors.Wrapf(ErrPasswordTooWeak, "password should contain at least one uppercase letter")
}
}
if c.Lcredit < 0 {
required := -c.Lcredit
if lowers < required {
return errors.Wrapf(ErrPasswordTooWeak, "password requires at least %d lowercase letter(s), got %d", required, lowers)
}
} else if c.Lcredit > 0 {
if lowers == 0 {
return errors.Wrapf(ErrPasswordTooWeak, "password should contain at least one lowercase letter")
}
}
if c.Ocredit < 0 {
required := -c.Ocredit
if others < required {
return errors.Wrapf(ErrPasswordTooWeak, "password requires at least %d special character(s), got %d", required, others)
}
} else if c.Ocredit > 0 {
if others == 0 {
return errors.Wrapf(ErrPasswordTooWeak, "password should contain at least one special character")
}
}
// 计算有效长度(考虑 credit 的正数值,用于减少长度要求)
effectiveLength := len(password)
if c.Dcredit > 0 {
effectiveLength += digits * c.Dcredit
}
if c.Ucredit > 0 {
effectiveLength += uppers * c.Ucredit
}
if c.Lcredit > 0 {
effectiveLength += lowers * c.Lcredit
}
if c.Ocredit > 0 {
effectiveLength += others * c.Ocredit
}
// 检查最小长度
if c.Minlen > 0 && effectiveLength < c.Minlen {
return errors.Wrapf(ErrPasswordTooWeak, "effective length %d is less than required %d", effectiveLength, c.Minlen)
}
// 检查最小字符类数量
if c.Minclass > 0 {
classes := 0
if digits > 0 {
classes++
}
if uppers > 0 {
classes++
}
if lowers > 0 {
classes++
}
if others > 0 {
classes++
}
if classes < c.Minclass {
return errors.Wrapf(ErrPasswordTooWeak, "requires at least %d character class(es), got %d", c.Minclass, classes)
}
}
// 检查最大重复字符数
if c.Maxrepeat > 0 {
maxRepeat := 0
currentRepeat := 1
prevChar := rune(0)
for _, r := range password {
if r == prevChar {
currentRepeat++
if currentRepeat > maxRepeat {
maxRepeat = currentRepeat
}
} else {
currentRepeat = 1
}
prevChar = r
}
if maxRepeat > c.Maxrepeat {
return errors.Wrapf(ErrPasswordTooWeak, "password contains more than %d consecutive repeated characters", c.Maxrepeat)
}
}
// 检查最大同类字符重复数
if c.Maxclassrepeat > 0 {
maxClassRepeat := 0
currentClassRepeat := 1
prevClass := -1 // -1: 未设置, 0: 数字, 1: 大写, 2: 小写, 3: 特殊
for _, r := range password {
var currentClass int
if unicode.IsDigit(r) {
currentClass = 0
} else if unicode.IsUpper(r) {
currentClass = 1
} else if unicode.IsLower(r) {
currentClass = 2
} else {
currentClass = 3
}
if currentClass == prevClass {
currentClassRepeat++
if currentClassRepeat > maxClassRepeat {
maxClassRepeat = currentClassRepeat
}
} else {
currentClassRepeat = 1
}
prevClass = currentClass
}
if maxClassRepeat > c.Maxclassrepeat {
return errors.Wrapf(ErrPasswordTooWeak, "password contains more than %d consecutive characters of the same class", c.Maxclassrepeat)
}
}
// 检查最大连续字符序列长度
// maxsequence 检查密码中是否存在超过指定长度的连续字符序列(如 "1234" 或 "abcd"
if c.Maxsequence > 0 {
runes := []rune(password)
for i := 0; i <= len(runes)-c.Maxsequence-1; i++ {
// 检查升序序列(如 "1234", "abcd"
isAscending := true
for j := 1; j <= c.Maxsequence; j++ {
if i+j >= len(runes) || runes[i+j] != runes[i+j-1]+1 {
isAscending = false
break
}
}
// 检查降序序列(如 "4321", "dcba"
isDescending := true
for j := 1; j <= c.Maxsequence; j++ {
if i+j >= len(runes) || runes[i+j] != runes[i+j-1]-1 {
isDescending = false
break
}
}
if isAscending || isDescending {
return errors.Wrapf(ErrPasswordTooWeak, "password contains a sequence of more than %d consecutive characters", c.Maxsequence)
}
}
}
// 检查密码中是否包含用户名
if c.Usercheck > 0 && username != "" {
// 将用户名和密码都转换为小写进行比较(不区分大小写)
lowerUsername := strings.ToLower(username)
lowerPassword := strings.ToLower(password)
// 检查密码中是否包含用户名(包括反向)
if strings.Contains(lowerPassword, lowerUsername) {
return errors.Wrapf(ErrPasswordTooWeak, "password contains the username")
}
// 检查密码中是否包含用户名的反向(用户名长度至少为3才检查反向)
if len(lowerUsername) >= 3 {
reversedUsername := reverseString(lowerUsername)
if strings.Contains(lowerPassword, reversedUsername) {
return errors.Wrapf(ErrPasswordTooWeak, "password contains the reversed username")
}
}
}
return nil
}
// reverseString 反转字符串
func reverseString(s string) string {
runes := []rune(s)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}
// ParsePAMConfig 解析 PAM 配置文件中的密码强度策略
// 支持 pam_pwquality 和 pam_cracklib 模块
//
// 兼容性说明:
// - enforcing 和 enforce_for_root 参数在 libpwquality 1.2.0+ 版本中支持
// - 较老的系统(如 RHEL 6 之前)可能不支持这些参数
// - 在 PAM 配置中,enforce_for_root 可能以独立标志形式出现(无值),如:
// password requisite pam_pwquality.so minlen=8 enforce_for_root
// 这种情况下,如果解析到 enforce_for_root 标志(无值),将设置为 1
// - 如果系统不支持这些参数,配置文件中不会出现,将使用默认值
func ParsePAMConfig(content []byte, config *Config) *Config {
if config == nil {
config = &Config{
Minlen: 0,
Dcredit: 0,
Ucredit: 0,
Lcredit: 0,
Ocredit: 0,
Minclass: 0,
Maxrepeat: 0,
Maxclassrepeat: 0,
Maxsequence: 0,
Enforcing: 1, // 默认值(1 表示强制执行)
EnforceForRoot: 0, // 默认值(0 表示不对 root 强制执行)
Usercheck: 0, // 默认值(0 表示不检查用户名)
}
}
lines := strings.Split(string(content), "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
// 跳过注释和空行
if len(line) == 0 || strings.HasPrefix(line, "#") {
continue
}
// 查找 password 相关的 PAM 配置行
// 格式: password requisite pam_pwquality.so retry=3 minlen=8 dcredit=-1 ucredit=-1
// 或: password requisite pam_cracklib.so retry=3 minlen=8 dcredit=-1 ucredit=-1
if !strings.Contains(line, "password") {
continue
}
// 检查是否包含 pam_pwquality 或 pam_cracklib
if !strings.Contains(line, "pam_pwquality") && !strings.Contains(line, "pam_cracklib") {
continue
}
// 解析参数,格式为 key=value 或独立标志(如 enforce_for_root
// 先找到 .so 后面的参数部分
parts := strings.Fields(line)
for _, part := range parts {
part = strings.TrimSpace(part)
if len(part) == 0 {
continue
}
// 检查是否是 key=value 格式
if strings.Contains(part, "=") {
kv := strings.SplitN(part, "=", 2)
if len(kv) != 2 {
continue
}
key := strings.TrimSpace(kv[0])
value := strings.TrimSpace(kv[1])
switch key {
case "minlen":
if v, err := strconv.Atoi(value); err == nil {
config.Minlen = v
}
case "dcredit":
if v, err := strconv.Atoi(value); err == nil {
config.Dcredit = v
}
case "ucredit":
if v, err := strconv.Atoi(value); err == nil {
config.Ucredit = v
}
case "lcredit":
if v, err := strconv.Atoi(value); err == nil {
config.Lcredit = v
}
case "ocredit":
if v, err := strconv.Atoi(value); err == nil {
config.Ocredit = v
}
case "minclass":
if v, err := strconv.Atoi(value); err == nil {
config.Minclass = v
}
case "maxrepeat":
if v, err := strconv.Atoi(value); err == nil {
config.Maxrepeat = v
}
case "maxclassrepeat":
if v, err := strconv.Atoi(value); err == nil {
config.Maxclassrepeat = v
}
case "maxsequence":
if v, err := strconv.Atoi(value); err == nil {
config.Maxsequence = v
}
case "enforcing":
if v, err := strconv.Atoi(value); err == nil {
config.Enforcing = v
}
case "enforce_for_root":
if v, err := strconv.Atoi(value); err == nil {
config.EnforceForRoot = v
}
case "usercheck":
if v, err := strconv.Atoi(value); err == nil {
config.Usercheck = v
}
case "difok": // pam_cracklib 特有:至少需要多少个字符与旧密码不同
// 这个参数不影响密码强度校验,可以忽略
case "retry": // 重试次数,不影响密码强度校验
}
} else {
// 处理独立标志(无值的参数)
// 例如:enforce_for_root(表示对 root 强制执行密码策略)
switch part {
case "enforce_for_root":
// 如果以独立标志形式出现,设置为 1(强制执行)
config.EnforceForRoot = 1
}
}
}
}
return config
}
// GeneratePassword 根据配置生成符合强度要求的密码
// passwordGenerator 是一个函数,接受长度参数并返回密码
// 如果 passwordGenerator 为 nil,将使用默认的最小长度 12
func (c *Config) GeneratePassword(passwordGenerator func(int) string) string {
if c == nil || !c.HasAnyPolicy() {
// 如果没有配置或配置为空,使用默认长度生成
if passwordGenerator != nil {
return passwordGenerator(12)
}
return ""
}
// 计算所需的最小密码长度
minLength := c.Minlen
if minLength == 0 {
minLength = 8 // 默认最小长度
}
// 根据 credit 要求计算额外需要的字符数
requiredChars := 0
if c.Dcredit < 0 {
requiredChars += -c.Dcredit
}
if c.Ucredit < 0 {
requiredChars += -c.Ucredit
}
if c.Lcredit < 0 {
requiredChars += -c.Lcredit
}
if c.Ocredit < 0 {
requiredChars += -c.Ocredit
}
// 确保长度满足所有要求
passwordLength := minLength
if requiredChars > 0 {
// 至少需要 minLength 和 requiredChars 中的较大值
if requiredChars > passwordLength {
passwordLength = requiredChars
}
// 再加上一些缓冲,确保有足够的字符满足 minclass 要求
if c.Minclass > 0 && c.Minclass > 1 {
passwordLength += c.Minclass
}
}
if passwordGenerator == nil {
return ""
}
// 生成密码并验证,直到符合要求
maxAttempts := 64
for i := 12; i < maxAttempts; i += 2 {
password := passwordGenerator(passwordLength)
// GeneratePassword 不提供用户名,所以传空字符串
if c.Validate(password, "") == nil {
return password
}
// 如果不符合要求,增加长度重试
passwordLength++
}
// 如果多次尝试都失败,返回一个较长的密码(应该能满足大部分要求)
return passwordGenerator(passwordLength)
}
File diff suppressed because it is too large Load Diff