keyring.go 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. package daemon
  2. import (
  3. "encoding/base64"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "log"
  8. "net/url"
  9. "git.aetherial.dev/aeth/yosai/pkg/keytags"
  10. )
  11. const (
  12. SSH_KEY = "ssh"
  13. API_KEY = "api_key"
  14. BEARER_AUTH = "bearer_auth"
  15. CLIENT_CREDENTIALS = "client_credentials"
  16. BASIC_AUTH = "basic_auth"
  17. LOGIN_CRED = "login_password"
  18. WIREGUARD = "wireguard"
  19. )
  20. type WireguardKeypair struct {
  21. PrivateKey string
  22. PublicKey string
  23. }
  24. func (w WireguardKeypair) GetPublic() string {
  25. return w.PublicKey
  26. }
  27. func (w WireguardKeypair) GetSecret() string {
  28. return w.PrivateKey
  29. }
  30. func (w WireguardKeypair) Prepare() string {
  31. return ""
  32. }
  33. func (w WireguardKeypair) GetType() string {
  34. return WIREGUARD
  35. }
  36. type VpsRootUser struct {
  37. Password string
  38. Pubkey string
  39. }
  40. type BearerAuth struct {
  41. Secret string // Likely would be the API key for the API
  42. }
  43. /*
  44. Format a bearer auth payload according to RFC 6750
  45. */
  46. func (b BearerAuth) Prepare() string {
  47. return fmt.Sprintf("Bearer %s", b.Secret)
  48. }
  49. /*
  50. Return the 'public' identifier, which for bearer auth the closest is going to be the auth type
  51. */
  52. func (b BearerAuth) GetPublic() string {
  53. return "Bearer"
  54. }
  55. /*
  56. Return the private data for this auth type
  57. */
  58. func (b BearerAuth) GetSecret() string {
  59. return b.Secret
  60. }
  61. func (b BearerAuth) GetType() string {
  62. return BEARER_AUTH
  63. }
  64. type BasicAuth struct {
  65. Username string // Username for basic auth
  66. Password string // subsequent password for basic auth
  67. }
  68. /*
  69. Encode a basic auth payload according to RFC 7617
  70. */
  71. func (b BasicAuth) Prepare() string {
  72. encodedcreds := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", b.Username, b.Password)))
  73. return fmt.Sprintf("Basic %s", encodedcreds)
  74. }
  75. /*
  76. Return the 'public' identifier, which for basic auth it will return the username
  77. */
  78. func (b BasicAuth) GetPublic() string {
  79. return b.Password
  80. }
  81. /*
  82. Return the private data for this auth type
  83. */
  84. func (b BasicAuth) GetSecret() string {
  85. return b.Password
  86. }
  87. func (b BasicAuth) GetType() string {
  88. return BASIC_AUTH
  89. }
  90. type ClientCredentials struct {
  91. ClientId string // Client ID for the API
  92. ClientSecret string // Client Secret for the API
  93. }
  94. /*
  95. Encode a client credentials type payload and return the payload string according to RFC 6749
  96. */
  97. func (c ClientCredentials) Prepare() string {
  98. credQuery := url.Values{}
  99. credQuery.Add("grant_type", "client_credentials")
  100. credQuery.Add("client_id", c.ClientId)
  101. credQuery.Add("client_secret", c.ClientSecret)
  102. return credQuery.Encode()
  103. }
  104. // return the client ID
  105. func (c ClientCredentials) GetPublic() string {
  106. return c.ClientId
  107. }
  108. // Return the Client Secret
  109. func (c ClientCredentials) GetSecret() string {
  110. return c.ClientSecret
  111. }
  112. func (c ClientCredentials) GetType() string {
  113. return CLIENT_CREDENTIALS
  114. }
  115. type SshKey struct {
  116. User string
  117. PrivateKey string
  118. }
  119. func (s SshKey) GetPublic() string {
  120. return s.User
  121. }
  122. func (s SshKey) GetSecret() string {
  123. return s.PrivateKey
  124. }
  125. func (s SshKey) Prepare() string {
  126. return s.PrivateKey
  127. }
  128. func (s SshKey) GetType() string {
  129. return SSH_KEY
  130. }
  131. type ApiKeyRing struct {
  132. Rungs []DaemonKeyRing
  133. Keys map[string]Key // hashmap with the keys in the keyring. Protected with getters and setters
  134. Config *ConfigFromFile
  135. KeyTagger keytags.Keytagger
  136. }
  137. /*
  138. Retrieve a keyring from the daemon keyring
  139. :param name: the name of the keyring. e.g., 'LINODE', or 'OPENWRT'
  140. */
  141. func (a *ApiKeyRing) GetKey(name string) (Key, error) {
  142. var key Key
  143. key, ok := a.Keys[name]
  144. if ok {
  145. return key, nil
  146. }
  147. if len(a.Rungs) > 0 {
  148. for i := range a.Rungs {
  149. key, err := a.Rungs[i].GetKey(name)
  150. if err != nil {
  151. if errors.Is(err, KeyNotFound) {
  152. a.Log("Key: ", name, "not found.", err.Error())
  153. continue
  154. }
  155. if errors.Is(err, KeyRingError) {
  156. a.Log("Error getting key:", name, err.Error())
  157. return key, err
  158. }
  159. a.Log("Unhandled exception getting key: ", name, err.Error())
  160. log.Fatal("Ungraceful shutdown. unhandled error within keyring: ", err)
  161. }
  162. if key.GetPublic() == "" || key.GetSecret() == "" {
  163. a.Log("null key: ", name, "returned.")
  164. continue
  165. }
  166. a.Log("Key:", name, "successfully added to the daemon keyring.")
  167. a.AddKey(name, key)
  168. return key, nil
  169. }
  170. }
  171. return key, KeyNotFound
  172. }
  173. /*
  174. Add a key to the daemon keyring
  175. :param name: name to give the key, used when indexing
  176. :param key: the Key struct to add to the keyring
  177. */
  178. func (a *ApiKeyRing) AddKey(name string, key Key) error {
  179. _, ok := a.Keys[name]
  180. if ok {
  181. return KeyExists
  182. }
  183. a.Keys[name] = key
  184. return nil
  185. }
  186. /*
  187. Remove a key from the daemon keyring
  188. :param name: the name that the key was given when adding to the keyring
  189. */
  190. func (a *ApiKeyRing) RemoveKey(name string) error {
  191. _, err := a.GetKey(name)
  192. if err != nil {
  193. return err
  194. }
  195. delete(a.Keys, name)
  196. return nil
  197. }
  198. // Return the resource name for logging purposes
  199. func (a *ApiKeyRing) Source() string {
  200. return "Base API Keyring"
  201. }
  202. /*
  203. Create a new daemon keyring. Passing additional implementers of the DaemonKeyRing will
  204. allow the GetKey() method on the toplevel keyring to search all subsequent keyrings for a match.
  205. */
  206. func NewKeyRing(cfg *ConfigFromFile, keytagger keytags.Keytagger) *ApiKeyRing {
  207. return &ApiKeyRing{
  208. Keys: map[string]Key{},
  209. Rungs: []DaemonKeyRing{},
  210. Config: cfg,
  211. KeyTagger: keytagger,
  212. }
  213. }
  214. func (a *ApiKeyRing) Log(msg ...string) {
  215. keyMsg := []string{
  216. "ApiKeyRing:",
  217. }
  218. keyMsg = append(keyMsg, msg...)
  219. a.Config.Log(keyMsg...)
  220. }
  221. type KeyringRequest struct {
  222. Public string `json:"public"`
  223. Secret string `json:"secret"`
  224. Type string `json:"type"`
  225. Name string `json:"name"`
  226. }
  227. /*
  228. Route handler for all requests for the Keyring component
  229. :param msg: a SockMessage struct containing the request information
  230. */
  231. func (a *ApiKeyRing) KeyringRouter(msg SockMessage) SockMessage {
  232. switch msg.Method {
  233. case "show":
  234. var req KeyringRequest
  235. err := json.Unmarshal(msg.Body, &req)
  236. if err != nil {
  237. return *NewSockMessage(MsgResponse, REQUEST_FAILED, []byte(err.Error()))
  238. }
  239. switch req.Name {
  240. case "all":
  241. b, err := json.Marshal(a.Keys)
  242. if err != nil {
  243. return *NewSockMessage(MsgResponse, REQUEST_FAILED, []byte(err.Error()))
  244. }
  245. return *NewSockMessage(MsgResponse, REQUEST_OK, b)
  246. default:
  247. key, err := a.GetKey(req.Name)
  248. if err != nil {
  249. return *NewSockMessage(MsgResponse, REQUEST_FAILED, []byte(err.Error()))
  250. }
  251. b, _ := json.Marshal(key)
  252. return *NewSockMessage(MsgResponse, REQUEST_OK, b)
  253. }
  254. case "reload":
  255. protectedKeys := a.KeyTagger.ProtectedKeys()
  256. keynames := []string{}
  257. for keyname := range a.Keys {
  258. _, ok := protectedKeys[keyname]
  259. if ok {
  260. continue
  261. }
  262. keynames = append(keynames, keyname)
  263. }
  264. for i := range keynames {
  265. delete(a.Keys, keynames[i])
  266. }
  267. a.Log("Keyring depleted, keys in keyring: ", fmt.Sprint(len(a.Keys)))
  268. a.Log("Keys to retrieve: ", fmt.Sprint(keynames))
  269. for i := range keynames {
  270. _, err := a.GetKey(keynames[i])
  271. if err != nil {
  272. a.Log("Keyring reload error, Error getting key: ", keynames[i], err.Error())
  273. }
  274. }
  275. return *NewSockMessage(MsgResponse, REQUEST_OK, []byte("Keyring successfully reloaded."))
  276. case "bootstrap":
  277. err := a.Bootstrap()
  278. if err != nil {
  279. return *NewSockMessage(MsgResponse, REQUEST_FAILED, []byte(err.Error()))
  280. }
  281. return *NewSockMessage(MsgResponse, REQUEST_OK, []byte("Keyring successfully bootstrapped."))
  282. default:
  283. return *NewSockMessage(MsgResponse, REQUEST_UNRESOLVED, []byte("Unresolvable method"))
  284. }
  285. }
  286. /*
  287. Bootstrap the keyring
  288. */
  289. func (a *ApiKeyRing) Bootstrap() error {
  290. allkeytags := a.KeyTagger.AllKeys()
  291. for i := range allkeytags {
  292. kn := allkeytags[i]
  293. _, err := a.GetKey(kn)
  294. if err != nil {
  295. return &KeyringBootstrapError{Msg: "Key with keytag: " + kn + " was not found on any of the daemon Keyring rungs."}
  296. }
  297. }
  298. return nil
  299. }
  300. /*
  301. ######################
  302. ##### INTERFACES #####
  303. ######################
  304. */
  305. type DaemonKeyRing interface {
  306. GetKey(string) (Key, error) // retrieve a key by its tag on the keyring
  307. AddKey(string, Key) error // Add a key to your keyring
  308. RemoveKey(string) error // Remove a key from the keyring
  309. Source() string // Return the name of the resource being called, i.e. 'Semaphone Keystore', or 'Hashicorp Vault'
  310. }
  311. type Key interface {
  312. // This function is supposed to return the payload for the given key type according to its RFC
  313. // i.e. if the 'type' is Bearer, then it returns a string with 'Bearer tokencode123456xyz'
  314. Prepare() string
  315. GetPublic() string // Get the public identifier of the key, i.e. the username, or client id, etc.
  316. GetSecret() string // Get the private/secret data, i.e. the password, API key, client secret, etc
  317. GetType() string // Returns the type of key. I.e. API_KEY, SSH_KEY, BASIC_AUTH, etc
  318. }
  319. /*
  320. ######################
  321. ##### ERRORS #####
  322. ######################
  323. */
  324. var (
  325. KeyNotFound = errors.New("Key not found.")
  326. KeyExists = errors.New("Key exists.")
  327. KeyRingError = errors.New("Unexpected error from child keyrung")
  328. )
  329. type KeyringBootstrapError struct {
  330. Msg string
  331. }
  332. func (k *KeyringBootstrapError) Error() string {
  333. return fmt.Sprintf("There was a fatal error bootstrapping the keyring: %s", k.Msg)
  334. }