99 lines
2.7 KiB
Go
99 lines
2.7 KiB
Go
package oci
|
||
|
||
import (
|
||
"fmt"
|
||
"strings"
|
||
)
|
||
|
||
// Credentials 是调用 OCI API 所需的完整凭据,私钥为 PEM 明文。
|
||
// CompartmentID 限定资源操作的目标 compartment,空表示租户根;
|
||
// 只影响 compute / 网络 / 块存储等资源查询,身份与订阅类调用始终走租户根。
|
||
type Credentials struct {
|
||
TenancyOCID string
|
||
UserOCID string
|
||
Region string
|
||
Fingerprint string
|
||
PrivateKey string
|
||
Passphrase string
|
||
CompartmentID string
|
||
// Proxy 非 nil 时该租户全部 SDK 出站请求经此代理
|
||
Proxy *ProxySpec
|
||
}
|
||
|
||
// EffectiveCompartment 返回资源操作的目标 compartment,未指定时为租户根。
|
||
func (c Credentials) EffectiveCompartment() *string {
|
||
if c.CompartmentID != "" {
|
||
id := c.CompartmentID
|
||
return &id
|
||
}
|
||
id := c.TenancyOCID
|
||
return &id
|
||
}
|
||
|
||
// Validate 检查凭据必填字段。
|
||
func (c Credentials) Validate() error {
|
||
switch {
|
||
case c.TenancyOCID == "":
|
||
return fmt.Errorf("credentials: tenancy is empty")
|
||
case c.UserOCID == "":
|
||
return fmt.Errorf("credentials: user is empty")
|
||
case c.Region == "":
|
||
return fmt.Errorf("credentials: region is empty")
|
||
case c.Fingerprint == "":
|
||
return fmt.Errorf("credentials: fingerprint is empty")
|
||
case !strings.Contains(c.PrivateKey, "PRIVATE KEY"):
|
||
return fmt.Errorf("credentials: private key is not a PEM")
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// ParseConfigINI 解析 OCI 标准 config(ini)文本的 [DEFAULT] 段。
|
||
// key_file 只在本机指向文件,导入场景私钥内容必须单独提供,因此忽略该行。
|
||
func ParseConfigINI(text string) (Credentials, error) {
|
||
var cred Credentials
|
||
section := "DEFAULT"
|
||
for _, line := range strings.Split(text, "\n") {
|
||
line = strings.TrimSpace(line)
|
||
if line == "" || strings.HasPrefix(line, "#") || strings.HasPrefix(line, ";") {
|
||
continue
|
||
}
|
||
if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
|
||
section = strings.TrimSpace(line[1 : len(line)-1])
|
||
continue
|
||
}
|
||
if !strings.EqualFold(section, "DEFAULT") {
|
||
continue
|
||
}
|
||
applyConfigLine(&cred, line)
|
||
}
|
||
if cred.TenancyOCID == "" && cred.UserOCID == "" {
|
||
return cred, fmt.Errorf("parse oci config: no recognizable fields")
|
||
}
|
||
return cred, nil
|
||
}
|
||
|
||
func applyConfigLine(cred *Credentials, line string) {
|
||
key, value, ok := strings.Cut(line, "=")
|
||
if !ok {
|
||
return
|
||
}
|
||
// OCID、指纹、region 值里不含 #,可安全去掉行尾注释
|
||
if i := strings.Index(value, "#"); i >= 0 {
|
||
value = value[:i]
|
||
}
|
||
key = strings.TrimSpace(strings.ToLower(key))
|
||
value = strings.TrimSpace(value)
|
||
switch key {
|
||
case "user":
|
||
cred.UserOCID = value
|
||
case "tenancy":
|
||
cred.TenancyOCID = value
|
||
case "fingerprint":
|
||
cred.Fingerprint = value
|
||
case "region":
|
||
cred.Region = value
|
||
case "pass_phrase":
|
||
cred.Passphrase = value
|
||
}
|
||
}
|