keyring.go 11 KB

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