keyring.go 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  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 *Configuration
  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 *Configuration, 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. Wrapping the show keyring function in a route friendly interface
  229. :param msg: a message to be decoded from the daemon socket
  230. */
  231. func (a *ApiKeyRing) ShowKeyringHandler(msg SockMessage) SockMessage {
  232. var req KeyringRequest
  233. err := json.Unmarshal(msg.Body, &req)
  234. if err != nil {
  235. return *NewSockMessage(MsgResponse, REQUEST_FAILED, []byte(err.Error()))
  236. }
  237. switch req.Name {
  238. case "all":
  239. b, err := json.Marshal(a.Keys)
  240. if err != nil {
  241. return *NewSockMessage(MsgResponse, REQUEST_FAILED, []byte(err.Error()))
  242. }
  243. return *NewSockMessage(MsgResponse, REQUEST_OK, b)
  244. default:
  245. key, err := a.GetKey(req.Name)
  246. if err != nil {
  247. return *NewSockMessage(MsgResponse, REQUEST_FAILED, []byte(err.Error()))
  248. }
  249. b, _ := json.Marshal(key)
  250. return *NewSockMessage(MsgResponse, REQUEST_OK, b)
  251. }
  252. }
  253. /*
  254. Wrapping the reload keyring function in a route friendly interface
  255. :param msg: a message to be decoded from the daemon socket
  256. */
  257. func (a *ApiKeyRing) ReloadKeyringHandler(msg SockMessage) SockMessage {
  258. protectedKeys := a.KeyTagger.ProtectedKeys()
  259. keynames := []string{}
  260. for keyname := range a.Keys {
  261. _, ok := protectedKeys[keyname]
  262. if ok {
  263. continue
  264. }
  265. keynames = append(keynames, keyname)
  266. }
  267. for i := range keynames {
  268. delete(a.Keys, keynames[i])
  269. }
  270. a.Log("Keyring depleted, keys in keyring: ", fmt.Sprint(len(a.Keys)))
  271. a.Log("Keys to retrieve: ", fmt.Sprint(keynames))
  272. for i := range keynames {
  273. _, err := a.GetKey(keynames[i])
  274. if err != nil {
  275. a.Log("Keyring reload error, Error getting key: ", keynames[i], err.Error())
  276. }
  277. }
  278. return *NewSockMessage(MsgResponse, REQUEST_OK, []byte("Keyring successfully reloaded."))
  279. }
  280. /*
  281. Wrapping the bootstrap keyring function in a route friendly interface
  282. :param msg: a message to be decoded from the daemon socket
  283. */
  284. func (a *ApiKeyRing) BootstrapKeyringHandler(msg SockMessage) SockMessage {
  285. err := a.Bootstrap()
  286. if err != nil {
  287. return *NewSockMessage(MsgResponse, REQUEST_FAILED, []byte(err.Error()))
  288. }
  289. return *NewSockMessage(MsgResponse, REQUEST_OK, []byte("Keyring successfully bootstrapped."))
  290. }
  291. /*
  292. Bootstrap the keyring
  293. */
  294. func (a *ApiKeyRing) Bootstrap() error {
  295. allkeytags := a.KeyTagger.AllKeys()
  296. for i := range allkeytags {
  297. kn := allkeytags[i]
  298. _, err := a.GetKey(kn)
  299. if err != nil {
  300. return &KeyringBootstrapError{Msg: "Key with keytag: " + kn + " was not found on any of the daemon Keyring rungs."}
  301. }
  302. }
  303. return nil
  304. }
  305. type KeyringRouter struct {
  306. routes map[Method]func(SockMessage) SockMessage
  307. }
  308. func (k *KeyringRouter) Register(method Method, callable func(SockMessage) SockMessage) {
  309. k.routes[method] = callable
  310. }
  311. func (k *KeyringRouter) Routes() map[Method]func(SockMessage) SockMessage {
  312. return k.routes
  313. }
  314. func NewKeyRingRouter() *KeyringRouter {
  315. return &KeyringRouter{routes: map[Method]func(SockMessage) SockMessage{}}
  316. }
  317. /*
  318. ######################
  319. ##### INTERFACES #####
  320. ######################
  321. */
  322. type DaemonKeyRing interface {
  323. GetKey(string) (Key, error) // retrieve a key by its tag on the keyring
  324. AddKey(string, Key) error // Add a key to your keyring
  325. RemoveKey(string) error // Remove a key from the keyring
  326. Source() string // Return the name of the resource being called, i.e. 'Semaphone Keystore', or 'Hashicorp Vault'
  327. }
  328. type Key interface {
  329. // This function is supposed to return the payload for the given key type according to its RFC
  330. // i.e. if the 'type' is Bearer, then it returns a string with 'Bearer tokencode123456xyz'
  331. Prepare() string
  332. GetPublic() string // Get the public identifier of the key, i.e. the username, or client id, etc.
  333. GetSecret() string // Get the private/secret data, i.e. the password, API key, client secret, etc
  334. GetType() string // Returns the type of key. I.e. API_KEY, SSH_KEY, BASIC_AUTH, etc
  335. }
  336. /*
  337. ######################
  338. ##### ERRORS #####
  339. ######################
  340. */
  341. var (
  342. KeyNotFound = errors.New("Key not found.")
  343. KeyExists = errors.New("Key exists.")
  344. KeyRingError = errors.New("Unexpected error from child keyrung")
  345. )
  346. type KeyringBootstrapError struct {
  347. Msg string
  348. }
  349. func (k *KeyringBootstrapError) Error() string {
  350. return fmt.Sprintf("There was a fatal error bootstrapping the keyring: %s", k.Msg)
  351. }