feat(16-03): add credential type parsers for RouterOS and SNMP
- SNMPCredential struct with v1/v2c/v3 field support - ParseRouterOSCredentials handles typed and legacy no-type-field JSON - ParseSNMPCredentials handles snmp_v1, snmp_v2c, snmp_v3 types - credentialEnvelope for type-agnostic type field peeking Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
103
poller/internal/vault/credential_types.go
Normal file
103
poller/internal/vault/credential_types.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package vault
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// SNMPCredential holds parsed SNMP credential fields after decryption.
|
||||
type SNMPCredential struct {
|
||||
Version string // "v1", "v2c", "v3"
|
||||
Community string // v1/v2c only
|
||||
SecurityLevel string // v3: "no_auth_no_priv", "auth_no_priv", "auth_priv"
|
||||
Username string // v3
|
||||
AuthProtocol string // v3: "MD5", "SHA", "SHA224", "SHA256", "SHA384", "SHA512"
|
||||
AuthPass string // v3
|
||||
PrivProtocol string // v3: "DES", "AES128", "AES192", "AES256"
|
||||
PrivPass string // v3
|
||||
}
|
||||
|
||||
// credentialEnvelope is the JSON structure common to all credential types.
|
||||
// Used to peek at the type field before choosing a type-specific parser.
|
||||
type credentialEnvelope struct {
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
// routerosCredentialJSON is the JSON shape for RouterOS credentials.
|
||||
type routerosCredentialJSON struct {
|
||||
Type string `json:"type"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
// snmpCredentialJSON is the JSON shape for all SNMP credential types.
|
||||
type snmpCredentialJSON struct {
|
||||
Type string `json:"type"`
|
||||
Community string `json:"community,omitempty"`
|
||||
SecurityLevel string `json:"security_level,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
AuthProtocol string `json:"auth_protocol,omitempty"`
|
||||
AuthPassphrase string `json:"auth_passphrase,omitempty"`
|
||||
PrivProtocol string `json:"priv_protocol,omitempty"`
|
||||
PrivPassphrase string `json:"priv_passphrase,omitempty"`
|
||||
}
|
||||
|
||||
// snmpTypeToVersion maps credential type strings to SNMP version identifiers.
|
||||
var snmpTypeToVersion = map[string]string{
|
||||
"snmp_v1": "v1",
|
||||
"snmp_v2c": "v2c",
|
||||
"snmp_v3": "v3",
|
||||
}
|
||||
|
||||
// ParseRouterOSCredentials extracts username and password from raw credential JSON.
|
||||
// It handles both typed credentials ({"type":"routeros",...}) and legacy credentials
|
||||
// without a type field ({"username":"admin","password":"secret"}).
|
||||
func ParseRouterOSCredentials(raw []byte) (username, password string, err error) {
|
||||
var env credentialEnvelope
|
||||
if err := json.Unmarshal(raw, &env); err != nil {
|
||||
return "", "", fmt.Errorf("unmarshal credential envelope: %w", err)
|
||||
}
|
||||
|
||||
// Legacy credentials have no type field -- treat as routeros.
|
||||
if env.Type != "" && env.Type != "routeros" {
|
||||
return "", "", fmt.Errorf("credential type %q is not routeros", env.Type)
|
||||
}
|
||||
|
||||
var creds routerosCredentialJSON
|
||||
if err := json.Unmarshal(raw, &creds); err != nil {
|
||||
return "", "", fmt.Errorf("unmarshal routeros credentials: %w", err)
|
||||
}
|
||||
|
||||
return creds.Username, creds.Password, nil
|
||||
}
|
||||
|
||||
// ParseSNMPCredentials extracts SNMP credential fields from raw credential JSON.
|
||||
// Supports snmp_v1, snmp_v2c, and snmp_v3 credential types.
|
||||
// Rejects RouterOS-type credentials and legacy credentials without a type field.
|
||||
func ParseSNMPCredentials(raw []byte) (*SNMPCredential, error) {
|
||||
var env credentialEnvelope
|
||||
if err := json.Unmarshal(raw, &env); err != nil {
|
||||
return nil, fmt.Errorf("unmarshal credential envelope: %w", err)
|
||||
}
|
||||
|
||||
version, ok := snmpTypeToVersion[env.Type]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("credential type %q is not an SNMP type", env.Type)
|
||||
}
|
||||
|
||||
var creds snmpCredentialJSON
|
||||
if err := json.Unmarshal(raw, &creds); err != nil {
|
||||
return nil, fmt.Errorf("unmarshal SNMP credentials: %w", err)
|
||||
}
|
||||
|
||||
return &SNMPCredential{
|
||||
Version: version,
|
||||
Community: creds.Community,
|
||||
SecurityLevel: creds.SecurityLevel,
|
||||
Username: creds.Username,
|
||||
AuthProtocol: creds.AuthProtocol,
|
||||
AuthPass: creds.AuthPassphrase,
|
||||
PrivProtocol: creds.PrivProtocol,
|
||||
PrivPass: creds.PrivPassphrase,
|
||||
}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user