keyring.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  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. }
  135. /*
  136. Retrieve a keyring from the daemon keyring
  137. :param name: the name of the keyring. e.g., 'LINODE', or 'OPENWRT'
  138. */
  139. func (a *ApiKeyRing) GetKey(name string) (Key, error) {
  140. var key Key
  141. key, ok := a.Keys[name]
  142. if ok {
  143. return key, nil
  144. }
  145. if len(a.Rungs) > 0 {
  146. for i := range a.Rungs {
  147. key, err := a.Rungs[i].GetKey(name)
  148. if err != nil {
  149. if errors.Is(err, KeyNotFound) {
  150. continue
  151. }
  152. if errors.Is(err, KeyRingError) {
  153. return key, err
  154. }
  155. log.Fatal("Ungraceful shutdown. unhandled error within keyring: ", err)
  156. }
  157. if key.GetPublic() == "" || key.GetSecret() == "" {
  158. continue
  159. }
  160. a.AddKey(name, key)
  161. return key, nil
  162. }
  163. }
  164. return key, KeyNotFound
  165. }
  166. /*
  167. Add a key to the daemon keyring
  168. :param name: name to give the key, used when indexing
  169. :param key: the Key struct to add to the keyring
  170. */
  171. func (a *ApiKeyRing) AddKey(name string, key Key) error {
  172. _, ok := a.Keys[name]
  173. if ok {
  174. return KeyExists
  175. }
  176. a.Keys[name] = key
  177. return nil
  178. }
  179. /*
  180. Remove a key from the daemon keyring
  181. :param name: the name that the key was given when adding to the keyring
  182. */
  183. func (a *ApiKeyRing) RemoveKey(name string) error {
  184. _, err := a.GetKey(name)
  185. if err != nil {
  186. return err
  187. }
  188. delete(a.Keys, name)
  189. return nil
  190. }
  191. // Return the resource name for logging purposes
  192. func (a *ApiKeyRing) Source() string {
  193. return "Base API Keyring"
  194. }
  195. /*
  196. Create a new daemon keyring. Passing additional implementers of the DaemonKeyRing will
  197. allow the GetKey() method on the toplevel keyring to search all subsequent keyrings for a match.
  198. */
  199. func NewKeyRing() *ApiKeyRing {
  200. return &ApiKeyRing{
  201. Keys: map[string]Key{},
  202. Rungs: []DaemonKeyRing{},
  203. }
  204. }
  205. type KeyringRequest struct {
  206. Public string `json:"public"`
  207. Secret string `json:"secret"`
  208. Type string `json:"type"`
  209. Name string `json:"name"`
  210. }
  211. /*
  212. Route handler for all requests for the Keyring component
  213. :param msg: a SockMessage struct containing the request information
  214. */
  215. func (a *ApiKeyRing) KeyringRouter(msg SockMessage) SockMessage {
  216. switch msg.Method {
  217. case "show":
  218. var req KeyringRequest
  219. err := json.Unmarshal(msg.Body, &req)
  220. if err != nil {
  221. return *NewSockMessage(MsgResponse, REQUEST_FAILED, []byte(err.Error()))
  222. }
  223. switch req.Name {
  224. case "all":
  225. b, err := json.Marshal(a.Keys)
  226. if err != nil {
  227. return *NewSockMessage(MsgResponse, REQUEST_FAILED, []byte(err.Error()))
  228. }
  229. return *NewSockMessage(MsgResponse, REQUEST_OK, b)
  230. default:
  231. key, err := a.GetKey(req.Name)
  232. if err != nil {
  233. return *NewSockMessage(MsgResponse, REQUEST_FAILED, []byte(err.Error()))
  234. }
  235. b, _ := json.Marshal(key)
  236. return *NewSockMessage(MsgResponse, REQUEST_OK, b)
  237. }
  238. case "bootstrap":
  239. err := a.Bootstrap(keytags.ConstKeytag{})
  240. if err != nil {
  241. return *NewSockMessage(MsgResponse, REQUEST_FAILED, []byte(err.Error()))
  242. }
  243. return *NewSockMessage(MsgResponse, REQUEST_OK, []byte("Keyring successfully bootstrapped."))
  244. default:
  245. return *NewSockMessage(MsgResponse, REQUEST_UNRESOLVED, []byte("Unresolvable method"))
  246. }
  247. }
  248. /*
  249. Bootstrap the keyring
  250. */
  251. func (a *ApiKeyRing) Bootstrap(keytagger keytags.Keytagger) error {
  252. allkeytags := keytagger.AllKeys()
  253. for i := range allkeytags {
  254. kn := allkeytags[i]
  255. _, err := a.GetKey(kn)
  256. if err != nil {
  257. return &KeyringBootstrapError{Msg: "Key with keytag: " + kn + " was not found on any of the daemon Keyring rungs."}
  258. }
  259. }
  260. return nil
  261. }
  262. /*
  263. ######################
  264. ##### INTERFACES #####
  265. ######################
  266. */
  267. type DaemonKeyRing interface {
  268. GetKey(string) (Key, error) // retrieve a key by its tag on the keyring
  269. AddKey(string, Key) error // Add a key to your keyring
  270. RemoveKey(string) error // Remove a key from the keyring
  271. Source() string // Return the name of the resource being called, i.e. 'Semaphone Keystore', or 'Hashicorp Vault'
  272. }
  273. type Key interface {
  274. // This function is supposed to return the payload for the given key type according to its RFC
  275. // i.e. if the 'type' is Bearer, then it returns a string with 'Bearer tokencode123456xyz'
  276. Prepare() string
  277. GetPublic() string // Get the public identifier of the key, i.e. the username, or client id, etc.
  278. GetSecret() string // Get the private/secret data, i.e. the password, API key, client secret, etc
  279. GetType() string // Returns the type of key. I.e. API_KEY, SSH_KEY, BASIC_AUTH, etc
  280. }
  281. /*
  282. ######################
  283. ##### ERRORS #####
  284. ######################
  285. */
  286. var (
  287. KeyNotFound = errors.New("Key not found.")
  288. KeyExists = errors.New("Key exists.")
  289. KeyRingError = errors.New("Unexpected error from child keyrung")
  290. )
  291. type KeyringBootstrapError struct {
  292. Msg string
  293. }
  294. func (k *KeyringBootstrapError) Error() string {
  295. return fmt.Sprintf("There was a fatal error bootstrapping the keyring: %s", k.Msg)
  296. }