Contains the Concourse pipeline definition for building a line-server container
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

116 lines
2.2 KiB

  1. package main
  2. import (
  3. "bufio"
  4. "encoding/base64"
  5. "log"
  6. "net/http"
  7. "os"
  8. "golang.org/x/crypto/scrypt"
  9. )
  10. const (
  11. scryptSalt = "linx-server"
  12. scryptN = 16384
  13. scryptr = 8
  14. scryptp = 1
  15. scryptKeyLen = 32
  16. )
  17. type AuthOptions struct {
  18. AuthFile string
  19. UnauthMethods []string
  20. }
  21. type auth struct {
  22. successHandler http.Handler
  23. failureHandler http.Handler
  24. authKeys []string
  25. o AuthOptions
  26. }
  27. func readAuthKeys(authFile string) []string {
  28. var authKeys []string
  29. f, err := os.Open(authFile)
  30. if err != nil {
  31. log.Fatal("Failed to open authfile: ", err)
  32. }
  33. defer f.Close()
  34. scanner := bufio.NewScanner(f)
  35. for scanner.Scan() {
  36. authKeys = append(authKeys, scanner.Text())
  37. }
  38. err = scanner.Err()
  39. if err != nil {
  40. log.Fatal("Scanner error while reading authfile: ", err)
  41. }
  42. return authKeys
  43. }
  44. func checkAuth(authKeys []string, key string) (result bool, err error) {
  45. checkKey, err := scrypt.Key([]byte(key), []byte(scryptSalt), scryptN, scryptr, scryptp, scryptKeyLen)
  46. if err != nil {
  47. return
  48. }
  49. encodedKey := base64.StdEncoding.EncodeToString(checkKey)
  50. for _, v := range authKeys {
  51. if encodedKey == v {
  52. result = true
  53. return
  54. }
  55. }
  56. result = false
  57. return
  58. }
  59. func (a auth) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  60. if sliceContains(a.o.UnauthMethods, r.Method) {
  61. // allow unauthenticated methods
  62. a.successHandler.ServeHTTP(w, r)
  63. return
  64. }
  65. key := r.Header.Get("Linx-Api-Key")
  66. result, err := checkAuth(a.authKeys, key)
  67. if err != nil || !result {
  68. a.failureHandler.ServeHTTP(w, r)
  69. return
  70. }
  71. a.successHandler.ServeHTTP(w, r)
  72. }
  73. func UploadAuth(o AuthOptions) func(http.Handler) http.Handler {
  74. fn := func(h http.Handler) http.Handler {
  75. return auth{
  76. successHandler: h,
  77. failureHandler: http.HandlerFunc(badAuthorizationHandler),
  78. authKeys: readAuthKeys(o.AuthFile),
  79. o: o,
  80. }
  81. }
  82. return fn
  83. }
  84. func badAuthorizationHandler(w http.ResponseWriter, r *http.Request) {
  85. w.WriteHeader(http.StatusUnauthorized)
  86. http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
  87. }
  88. func sliceContains(slice []string, s string) bool {
  89. for _, v := range slice {
  90. if s == v {
  91. return true
  92. }
  93. }
  94. return false
  95. }