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.
 
 
 

100 lines
2.4 KiB

  1. // Copyright 2015 Google Inc. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // Package ipauth provides a martian.Modifier that sets auth based on IP.
  15. package ipauth
  16. import (
  17. "net"
  18. "net/http"
  19. "github.com/google/martian"
  20. "github.com/google/martian/auth"
  21. )
  22. var noop = martian.Noop("ipauth.Modifier")
  23. // Modifier is the IP authentication modifier.
  24. type Modifier struct {
  25. reqmod martian.RequestModifier
  26. resmod martian.ResponseModifier
  27. }
  28. // NewModifier returns a new IP authentication modifier.
  29. func NewModifier() *Modifier {
  30. return &Modifier{
  31. reqmod: noop,
  32. resmod: noop,
  33. }
  34. }
  35. // SetRequestModifier sets the request modifier.
  36. func (m *Modifier) SetRequestModifier(reqmod martian.RequestModifier) {
  37. if reqmod == nil {
  38. reqmod = noop
  39. }
  40. m.reqmod = reqmod
  41. }
  42. // SetResponseModifier sets the response modifier.
  43. func (m *Modifier) SetResponseModifier(resmod martian.ResponseModifier) {
  44. if resmod == nil {
  45. resmod = noop
  46. }
  47. m.resmod = resmod
  48. }
  49. // ModifyRequest sets the auth ID in the context from the request iff it has
  50. // not already been set and runs reqmod.ModifyRequest. If the underlying
  51. // modifier has indicated via auth error that no valid auth credentials
  52. // have been found we set ctx.SkipRoundTrip.
  53. func (m *Modifier) ModifyRequest(req *http.Request) error {
  54. ctx := martian.NewContext(req)
  55. actx := auth.FromContext(ctx)
  56. ip, _, err := net.SplitHostPort(req.RemoteAddr)
  57. if err != nil {
  58. ip = req.RemoteAddr
  59. }
  60. actx.SetID(ip)
  61. err = m.reqmod.ModifyRequest(req)
  62. if actx.Error() != nil {
  63. ctx.SkipRoundTrip()
  64. }
  65. return err
  66. }
  67. // ModifyResponse runs resmod.ModifyResponse.
  68. //
  69. // If an error is returned from resmod.ModifyResponse it is returned.
  70. func (m *Modifier) ModifyResponse(res *http.Response) error {
  71. ctx := martian.NewContext(res.Request)
  72. actx := auth.FromContext(ctx)
  73. err := m.resmod.ModifyResponse(res)
  74. if actx.Error() != nil {
  75. res.StatusCode = 403
  76. res.Status = http.StatusText(403)
  77. }
  78. return err
  79. }