-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 7697c1f
Showing
14 changed files
with
359 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
on: | ||
push: | ||
branches: | ||
- master | ||
pull_request: | ||
branches: | ||
- master | ||
|
||
name: run tests | ||
jobs: | ||
lint: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Install Go | ||
uses: actions/setup-go@v2 | ||
with: | ||
go-version: 1.15.x | ||
- name: Checkout code | ||
uses: actions/checkout@v2 | ||
- name: Run linters | ||
uses: golangci/golangci-lint-action@v2 | ||
with: | ||
version: v1.29 | ||
|
||
test: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v2 | ||
- name: Run tests | ||
run: go test -v github.com/jandelgado/rabbitmq-http-auth/pkg |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
*~ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
ARG registry | ||
FROM golang:1.16 as builder | ||
|
||
RUN mkdir -p /build | ||
COPY . /build | ||
RUN cd /build/cmd && \ | ||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -tags netgo -ldflags '-w -extldflags "-static"' -o rabbitmq-http-auth . | ||
|
||
FROM scratch | ||
|
||
COPY --from=builder /build/cmd/rabbitmq-http-auth / | ||
|
||
WORKDIR /app | ||
ENTRYPOINT ["/rabbitmq-http-auth"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# RabbitMQ HTTP Auth Backend in Go | ||
|
||
Package and example service to build a RabbitMQ HTTP service for use with | ||
the RabbitMQ "HTTP Auth Backend" (actually it is an AuthN/AuthZ backend). | ||
|
||
For details see https://github.com/rabbitmq/rabbitmq-server/tree/master/deps/rabbitmq_auth_backend_http | ||
|
||
## Build your own service | ||
|
||
TODO | ||
|
||
## Testing it | ||
|
||
After starting the demo app either manually or by running | ||
`docker docker run --rm -ti -p8000:8000 rabbitmq-http-auth:latest`, we | ||
can test the service by issueing POST requests to the `User` endpoint , | ||
for example: | ||
|
||
```sh | ||
$ curl -XPOST localhost:8000/auth/user -d "username=guest&pasword=test" | ||
allow [management administrator demo] | ||
$ curl -XPOST localhost:8000/auth/user -d "username=john&pasword=test" | ||
deny | ||
``` | ||
|
||
Since the `DemoAuthenticator` only allows the `guest` user, this is the | ||
expected result. | ||
|
||
## Test with RabbitMQ | ||
|
||
A docker-compose file is provided which sets up a RabbitMQ broker with the | ||
authentication service configured. To test it, run: | ||
|
||
```sh | ||
$ cd demo && docker-compose up | ||
``` | ||
|
||
Then in another console, try to publish a message using [rabtap](TODO) | ||
```sh | ||
$ echo "hello" | rabtap pub --uri amqp://guest:123@localhost:5672 --exchange amq.topic --routingkey "#" | ||
``` | ||
|
||
In the docker-compose log, should see the authenticator logging the request: | ||
``` | ||
auth-http_1 | 2021/04/18 21:28:01 auth user(u=guest) -> allow [management administrator demo] | ||
``` | ||
|
||
As the `DemoAuthenticator` allows any password for the guest user, you can | ||
try to change the password in the `rabtap` command or try to login on the | ||
[management console](http://localhost:15672) with any password. | ||
|
||
## Author & License | ||
|
||
(c) Copyright 2021 by Jan Delgado. Licence: MIT | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// rabbitmq-http-auth - demo implementation of the Authenticator interface, | ||
// which allows the user guest with ANY password to be authorized for | ||
// everything. | ||
// (c) copyright 2021 by Jan Delgado | ||
package main | ||
|
||
import ( | ||
auth "github.com/jandelgado/rabbitmq-http-auth/pkg" | ||
) | ||
|
||
type DemoAuthenticator struct{} | ||
|
||
func (s DemoAuthenticator) String() string { | ||
return "DemoAuthenticator" | ||
} | ||
|
||
func (s DemoAuthenticator) Resource(username, vhost, resource, name, permission string) auth.Decision { | ||
return true | ||
} | ||
|
||
func (s DemoAuthenticator) User(username, password string) (auth.Decision, string) { | ||
return username == "guest", "management administrator demo" | ||
} | ||
|
||
func (s DemoAuthenticator) VHost(username, vhost, ip string) auth.Decision { | ||
return true | ||
} | ||
|
||
func (s DemoAuthenticator) Topic(username, vhost, resource, name, permission, routing_key string) auth.Decision { | ||
return true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// rabbitmq-http-auth - exmple authentication service using a demo authenticator | ||
// (c) copyright 2021 by Jan Delgadoauthenticator} | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"net/http" | ||
"time" | ||
|
||
auth "github.com/jandelgado/rabbitmq-http-auth/pkg" | ||
) | ||
|
||
const httpReadTimeout = 10 * time.Second | ||
const httpWriteTimeout = 10 * time.Second | ||
|
||
func main() { | ||
a := DemoAuthenticator{} | ||
authenticator := auth.NewLogInterceptingAuthenticator(a) | ||
s := auth.NewAuthServer(authenticator) | ||
|
||
srv := &http.Server{ | ||
Handler: s.NewRouter(), | ||
Addr: fmt.Sprintf(":%d", 8000), | ||
WriteTimeout: httpWriteTimeout, | ||
ReadTimeout: httpReadTimeout, | ||
} | ||
|
||
err := srv.ListenAndServe() | ||
|
||
if err != nil { | ||
panic(err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
version: '3' | ||
services: | ||
auth-http: | ||
build: | ||
context: ../ | ||
ports: | ||
- "8000:8000" | ||
|
||
rabbitmq: | ||
image: rabbitmq:3.8-management-alpine | ||
volumes: | ||
- ./definitions.json:/etc/rabbitmq/definitions.json:z | ||
- ./rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf:z | ||
ports: | ||
- 5672:5672 | ||
- 15672:15672 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
log.default.level = debug | ||
loopback_users = none | ||
|
||
listeners.tcp.default = 5672 | ||
management.tcp.port = 15672 | ||
|
||
|
||
auth_backends.1 = http | ||
auth_http.http_method = post | ||
auth_http.user_path = http://auth-http:8000/auth/user | ||
auth_http.vhost_path = http://auth-http:8000/auth/vhost | ||
auth_http.resource_path = http://auth-http:8000/auth/resource | ||
auth_http.topic_path = http://auth-http:8000/auth/topic | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module github.com/jandelgado/rabbitmq-http-auth | ||
|
||
go 1.15 | ||
|
||
require github.com/gorilla/mux v1.8.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= | ||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// rabbitmq-http-auth - Authenicator interface | ||
// (c) copyright 2021 by Jan Delgado | ||
package rabbitmqauth | ||
|
||
type Decision bool | ||
|
||
const ( | ||
Allow Decision = true | ||
Deny Decision = false | ||
) | ||
|
||
// Authenticator instances make the actual decisions on authentication | ||
// requests by RabboitMQ. Every function returns the authentication decision, | ||
// which is always Allow or Deny. | ||
// | ||
// See https://github.com/rabbitmq/rabbitmq-server/tree/master/deps/rabbitmq_auth_backend_http | ||
// for a detailed description. | ||
type Authenticator interface { | ||
// User authenticates the given user. In addition to the decision, the tags | ||
// associated with the user are returned. | ||
User(username, password string) (Decision, string) | ||
// VHost checks if the given user/ip combination is allowed to access the | ||
// vhosts | ||
VHost(username, vhost, ip string) Decision | ||
// Resource checks if the given user has access to the presented resource | ||
Resource(username, vhost, resource, name, permission string) Decision | ||
// Topic checks if the given user has access to the presented topic when | ||
// using topic authorization (https://www.rabbitmq.com/access-control.html#topic-authorisation) | ||
Topic(username, vhost, resource, name, permission, routing_key string) Decision | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// rabbitmq-http-auth - log authentication requests | ||
// (c) copyright 2021 by Jan Delgado | ||
package rabbitmqauth | ||
|
||
import ( | ||
"log" | ||
) | ||
|
||
type LogInterceptingAuthenticator struct { | ||
authenticator Authenticator | ||
} | ||
|
||
func NewLogInterceptingAuthenticator(authenticator Authenticator) Authenticator { | ||
return LogInterceptingAuthenticator{authenticator} | ||
} | ||
|
||
func (s LogInterceptingAuthenticator) String() string { | ||
return "LogInterceptingAuthenticator" | ||
} | ||
|
||
func (s LogInterceptingAuthenticator) User(username, password string) (Decision, string) { | ||
res, tags := s.authenticator.User(username, password) | ||
log.Printf("auth user(u=%s) -> %v [%s]", username, res, tags) | ||
return res, tags | ||
} | ||
|
||
func (s LogInterceptingAuthenticator) VHost(username, vhost, ip string) Decision { | ||
res := s.authenticator.VHost(username, vhost, ip) | ||
log.Printf("auth vhost(u=%s,v=%s,i=%s) -> %v", username, vhost, ip, res) | ||
return res | ||
} | ||
|
||
func (s LogInterceptingAuthenticator) Resource(username, vhost, resource, name, permission string) Decision { | ||
res := s.authenticator.Resource(username, vhost, resource, name, permission) | ||
log.Printf("auth resource(u=%s,v=%s,r=%s,n=%s,p=%s) -> %v", | ||
username, vhost, resource, name, permission, res) | ||
return res | ||
} | ||
|
||
func (s LogInterceptingAuthenticator) Topic(username, vhost, resource, name, permission, routing_key string) Decision { | ||
res := s.authenticator.Topic(username, vhost, resource, name, permission, routing_key) | ||
log.Printf("auth topic(u=%s,v=%s,r=%s,n=%s,p=%s,k=%s) -> %v", | ||
username, vhost, resource, name, permission, routing_key, res) | ||
return res | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// rabbitmq-http-auth - http router | ||
// (c) copyright 2021 by Jan Delgado | ||
package rabbitmqauth | ||
|
||
import ( | ||
"fmt" | ||
"net/http" | ||
"time" | ||
|
||
"github.com/gorilla/mux" | ||
) | ||
|
||
const httpReadTimeout = 15 * time.Second | ||
const httpWriteTimeout = 45 * time.Second | ||
|
||
type AuthServer struct { | ||
authenticator Authenticator | ||
} | ||
|
||
func NewAuthServer(authenticator Authenticator) AuthServer { | ||
return AuthServer{authenticator} | ||
} | ||
|
||
func (s Decision) String() string { | ||
if s { | ||
return "allow" | ||
} | ||
return "deny" | ||
} | ||
|
||
func validatePostArgs(args []string, r *http.Request) map[string]string { | ||
result := map[string]string{} | ||
for _, s := range args { | ||
result[s] = r.PostFormValue(s) | ||
} | ||
return result | ||
} | ||
|
||
func (s *AuthServer) userHandler(w http.ResponseWriter, r *http.Request) { | ||
args := validatePostArgs([]string{"username", "password"}, r) | ||
res, tags := s.authenticator.User(args["username"], args["password"]) | ||
if res { | ||
fmt.Fprintf(w, "%s [%s]", res, tags) | ||
} else { | ||
fmt.Fprintf(w, "%s", res) | ||
} | ||
} | ||
|
||
func (s *AuthServer) vhostHandler(w http.ResponseWriter, r *http.Request) { | ||
args := validatePostArgs([]string{"username", "vhost", "ip"}, r) | ||
res := s.authenticator.VHost(args["username"], args["vhost"], args["ip"]) | ||
fmt.Fprintf(w, "%s", res) | ||
} | ||
|
||
func (s *AuthServer) topicHandler(w http.ResponseWriter, r *http.Request) { | ||
args := validatePostArgs([]string{"username", "vhost", "resource", "name", "permission", "routing_key"}, r) | ||
res := s.authenticator.Topic(args["username"], args["vhost"], | ||
args["resource"], args["name"], args["permission"], args["routing_key"]) | ||
fmt.Fprintf(w, "%s", res) | ||
} | ||
|
||
func (s *AuthServer) resourceHandler(w http.ResponseWriter, r *http.Request) { | ||
args := validatePostArgs([]string{"username", "vhost", "resource", "name", "permission"}, r) | ||
res := s.authenticator.Resource(args["username"], args["vhost"], | ||
args["resource"], args["name"], args["permission"]) | ||
fmt.Fprintf(w, "%s", res) | ||
} | ||
|
||
func (s *AuthServer) NewRouter() http.Handler { | ||
router := mux.NewRouter() | ||
router.HandleFunc("/auth/user", s.userHandler).Methods("POST") | ||
router.HandleFunc("/auth/vhost", s.vhostHandler).Methods("POST") | ||
router.HandleFunc("/auth/resource", s.resourceHandler).Methods("POST") | ||
router.HandleFunc("/auth/topic", s.topicHandler).Methods("POST") | ||
return router | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package rabbitmqauth | ||
|
||
import "testing" | ||
|
||
func TestUserRequestIsServerd(t *testing.T) { | ||
} |