chore: auto init agent ingest user (#120)
* chore: auto init agent ingest user * docs: update release notes --------- Co-authored-by: hardy <luohf@infinilabs.com>
This commit is contained in:
parent
2f94f14d79
commit
60eac5ebf6
|
@ -52,8 +52,8 @@ pipeline:
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
body: $[[message]]
|
body: $[[message]]
|
||||||
basic_auth:
|
basic_auth:
|
||||||
username: $[[SETUP_ES_USERNAME]]
|
username: $[[SETUP_AGENT_USERNAME]]
|
||||||
password: $[[SETUP_ES_PASSWORD]]
|
password: $[[SETUP_AGENT_PASSWORD]]
|
||||||
# tls: #for mTLS connection with config servers
|
# tls: #for mTLS connection with config servers
|
||||||
# enabled: true
|
# enabled: true
|
||||||
# ca_file: /xxx/ca.crt
|
# ca_file: /xxx/ca.crt
|
||||||
|
|
|
@ -18,14 +18,16 @@ Information about release notes of INFINI Console is provided here.
|
||||||
|
|
||||||
### Improvements
|
### Improvements
|
||||||
|
|
||||||
- add Copy request to alerting chart
|
- Add Buckets Diff to alerting rule
|
||||||
- add credential settings for agent in enrolling agent
|
- Automatically create Agent metrics for system clusters when using Easysearch to store metrics Write least-privileged user (#120)
|
||||||
- add collection mode to cluster editing
|
- Add Copy request to alerting chart
|
||||||
|
- Add credential settings for agent in enrolling agent
|
||||||
|
- Add collection mode to cluster editing
|
||||||
|
|
||||||
## 1.28.1 (2025-01-24)
|
## 1.28.1 (2025-01-24)
|
||||||
|
|
||||||
- add credential settings for agent in enrolling agent
|
- Add credential settings for agent in enrolling agent
|
||||||
- add collection mode to cluster editing
|
- Add collection mode to cluster editing
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ title: "版本历史"
|
||||||
- 告警图表新增复制请求
|
- 告警图表新增复制请求
|
||||||
- 在注册 Agent 中新增 Agent 凭据设置
|
- 在注册 Agent 中新增 Agent 凭据设置
|
||||||
- 在集群编辑中新增采集模式
|
- 在集群编辑中新增采集模式
|
||||||
|
- 当使用 Easysearch 存储指标时,自动为系统集群创建 Agent 指标写入最小权限用户 (#120)
|
||||||
|
|
||||||
## 1.28.1 (2025-01-24)
|
## 1.28.1 (2025-01-24)
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,8 @@ import (
|
||||||
"infini.sh/framework/plugins/replay"
|
"infini.sh/framework/plugins/replay"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const ingestUser = "infini_ingest"
|
||||||
|
|
||||||
type Module struct {
|
type Module struct {
|
||||||
api.Handler
|
api.Handler
|
||||||
}
|
}
|
||||||
|
@ -492,30 +494,9 @@ func (module *Module) initialize(w http.ResponseWriter, r *http.Request, ps http
|
||||||
if reuseOldCred {
|
if reuseOldCred {
|
||||||
toSaveCfg.CredentialID = oldCfg.CredentialID
|
toSaveCfg.CredentialID = oldCfg.CredentialID
|
||||||
} else {
|
} else {
|
||||||
cred := credential.Credential{
|
credId := createCred("INFINI_SYSTEM", request.Cluster.Username, request.Cluster.Password)
|
||||||
Name: "INFINI_SYSTEM",
|
cfg.CredentialID = credId
|
||||||
Type: credential.BasicAuth,
|
toSaveCfg.CredentialID = credId
|
||||||
Tags: []string{"infini", "system"},
|
|
||||||
Payload: map[string]interface{}{
|
|
||||||
"basic_auth": map[string]interface{}{
|
|
||||||
"username": request.Cluster.Username,
|
|
||||||
"password": request.Cluster.Password,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
cred.ID = util.GetUUID()
|
|
||||||
err = cred.Encode()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
toSaveCfg.CredentialID = cred.ID
|
|
||||||
cfg.CredentialID = cred.ID
|
|
||||||
now := time.Now()
|
|
||||||
cred.Created = &now
|
|
||||||
err = orm.Save(nil, &cred)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
toSaveCfg.BasicAuth = nil
|
toSaveCfg.BasicAuth = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -598,6 +579,7 @@ func (module *Module) initialize(w http.ResponseWriter, r *http.Request, ps http
|
||||||
|
|
||||||
success = true
|
success = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (module *Module) validateSecret(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
func (module *Module) validateSecret(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
err, client, request := module.initTempClient(r)
|
err, client, request := module.initTempClient(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -659,6 +641,34 @@ func validateCredentialSecret(ormHandler orm.ORM, credentialSecret string) (bool
|
||||||
return exists, nil
|
return exists, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createCred(name, username, password string) string {
|
||||||
|
cred := credential.Credential{
|
||||||
|
Name: name,
|
||||||
|
Type: credential.BasicAuth,
|
||||||
|
Tags: []string{"infini", "system"},
|
||||||
|
Payload: map[string]interface{}{
|
||||||
|
"basic_auth": map[string]interface{}{
|
||||||
|
"username": username,
|
||||||
|
"password": password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cred.ID = util.GetUUID()
|
||||||
|
err := cred.Encode()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
cred.Created = &now
|
||||||
|
cred.Updated = &now
|
||||||
|
err = orm.Save(nil, &cred)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return cred.ID
|
||||||
|
}
|
||||||
|
|
||||||
func getYamlData(filename string) []byte {
|
func getYamlData(filename string) []byte {
|
||||||
baseDir := path.Join(global.Env().GetConfigDir(), "setup")
|
baseDir := path.Join(global.Env().GetConfigDir(), "setup")
|
||||||
filePath := path.Join(baseDir, "common", "data", filename)
|
filePath := path.Join(baseDir, "common", "data", filename)
|
||||||
|
@ -775,6 +785,21 @@ func (module *Module) initializeTemplate(w http.ResponseWriter, r *http.Request,
|
||||||
}, http.StatusOK)
|
}, http.StatusOK)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Easysearch auto create ingest user
|
||||||
|
ingestPassword := util.GenerateRandomString(20)
|
||||||
|
if ver.Distribution == elastic.Easysearch {
|
||||||
|
err = keystore.SetValue("SYSTEM_CLUSTER_INGEST_PASSWORD", []byte(ingestPassword))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
client := elastic.GetClient(GlobalSystemElasticsearchID)
|
||||||
|
err = initIngestUser(client, cfg1.IndexPrefix, ingestUser, ingestPassword)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
output := tpl.ExecuteFuncString(func(w io.Writer, tag string) (int, error) {
|
output := tpl.ExecuteFuncString(func(w io.Writer, tag string) (int, error) {
|
||||||
switch tag {
|
switch tag {
|
||||||
case "SETUP_SYSTEM_INGEST_CONFIG":
|
case "SETUP_SYSTEM_INGEST_CONFIG":
|
||||||
|
@ -795,6 +820,18 @@ func (module *Module) initializeTemplate(w http.ResponseWriter, r *http.Request,
|
||||||
return w.Write([]byte(request.Cluster.Username))
|
return w.Write([]byte(request.Cluster.Username))
|
||||||
case "SETUP_ES_PASSWORD":
|
case "SETUP_ES_PASSWORD":
|
||||||
return w.Write([]byte(request.Cluster.Password))
|
return w.Write([]byte(request.Cluster.Password))
|
||||||
|
case "SETUP_AGENT_USERNAME":
|
||||||
|
if ver.Distribution == elastic.Easysearch {
|
||||||
|
return w.Write([]byte(ingestUser))
|
||||||
|
} else {
|
||||||
|
return w.Write([]byte(request.Cluster.Username))
|
||||||
|
}
|
||||||
|
case "SETUP_AGENT_PASSWORD":
|
||||||
|
if ver.Distribution == elastic.Easysearch {
|
||||||
|
return w.Write([]byte(ingestPassword))
|
||||||
|
} else {
|
||||||
|
return w.Write([]byte(request.Cluster.Password))
|
||||||
|
}
|
||||||
case "SETUP_SCHEME":
|
case "SETUP_SCHEME":
|
||||||
return w.Write([]byte(strings.Split(request.Cluster.Endpoint, "://")[0]))
|
return w.Write([]byte(strings.Split(request.Cluster.Endpoint, "://")[0]))
|
||||||
case "SETUP_ENDPOINTS":
|
case "SETUP_ENDPOINTS":
|
||||||
|
@ -867,3 +904,41 @@ func (module *Module) initializeTemplate(w http.ResponseWriter, r *http.Request,
|
||||||
}, http.StatusOK)
|
}, http.StatusOK)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func initIngestUser(client elastic.API, indexPrefix string, username, password string) error {
|
||||||
|
roleTpl := `{
|
||||||
|
"cluster": [
|
||||||
|
"cluster_monitor",
|
||||||
|
"cluster_composite_ops"
|
||||||
|
],
|
||||||
|
"description": "Provide the minimum permissions for INFINI AGENT to write metrics and logs",
|
||||||
|
"indices": [{
|
||||||
|
"names": [
|
||||||
|
"%slogs*", "%smetrics*"
|
||||||
|
],
|
||||||
|
"query": "",
|
||||||
|
"field_security": [],
|
||||||
|
"field_mask": [],
|
||||||
|
"privileges": [
|
||||||
|
"create_index","index","manage_aliases","write"
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}`
|
||||||
|
roleBody := fmt.Sprintf(roleTpl, indexPrefix, indexPrefix)
|
||||||
|
err := client.PutRole(ingestUser, []byte(roleBody))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create ingest role: %w", err)
|
||||||
|
}
|
||||||
|
userTpl := `{
|
||||||
|
"roles": [
|
||||||
|
"%s"
|
||||||
|
],
|
||||||
|
"password": "%s"}`
|
||||||
|
|
||||||
|
userBody := fmt.Sprintf(userTpl, ingestUser, password)
|
||||||
|
err = client.PutUser(username, []byte(userBody))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create ingest user: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue