-
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.
[GCloud][Auth] Add GCloudServiceAccount middleware
- Loading branch information
Showing
6 changed files
with
1,292 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
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,41 @@ | ||
# GAPI Addons | ||
|
||
----- | ||
|
||
A repo with a list of additional packages to improve GAPI features | ||
|
||
## How it works | ||
|
||
----- | ||
|
||
First choose your package(s) and add it using go modules, here is an example for [auth.GCloudServiceAccount](https://pkg.go.dev/github.com/mwm-io/gapi-addons/gcloud/middleware/auth#GCloudServiceAccount): | ||
```sh | ||
$ get get github.com/mwm-io/gapi-addons/gcloud/middleware/auth@latest | ||
``` | ||
|
||
The use it in you code: | ||
|
||
```go | ||
package main | ||
|
||
import ( | ||
... | ||
github.com/mwm-io/gapi-addons/gcloud/middleware/auth | ||
) | ||
|
||
type myHandler struct { | ||
handler.WithMiddlewares | ||
} | ||
|
||
func NewHandler() handler.Handler { | ||
var h myHandler | ||
|
||
h.MiddlewareList = []handler.Middleware{ | ||
auth.GCloudServiceAccount{ | ||
ServiceAccount: "[email protected]", | ||
}, | ||
} | ||
... | ||
} | ||
``` | ||
|
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 @@ | ||
> All Google Cloud specific packages must be here. |
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,102 @@ | ||
package auth | ||
|
||
import ( | ||
"net/http" | ||
"strings" | ||
|
||
"github.com/mwm-io/gapi/errors" | ||
"github.com/mwm-io/gapi/handler" | ||
"github.com/mwm-io/gapi/openapi" | ||
"github.com/swaggest/openapi-go/openapi3" | ||
"google.golang.org/api/idtoken" | ||
) | ||
|
||
// AuthorizationHeader const for header used for authorization token | ||
const AuthorizationHeader = "Authorization" | ||
|
||
// GCloudServiceAccount is a middleware that will check AuthorizationHeader for incoming request. | ||
// The expected header value is an OpenID Token generated by Google Cloud for given ServiceAccount. | ||
type GCloudServiceAccount struct { | ||
ServiceAccount string | ||
} | ||
|
||
// Wrap implements the handler.Middleware interface | ||
func (m GCloudServiceAccount) Wrap(h handler.Handler) handler.Handler { | ||
return handler.Func(func(w http.ResponseWriter, r *http.Request) (interface{}, error) { | ||
token := r.Header.Get(AuthorizationHeader) | ||
if token == "" { | ||
return nil, errors.Err("access forbidden").WithStatus(http.StatusForbidden) | ||
} | ||
|
||
splitAuthHeader := strings.Split(token, " ") | ||
if len(splitAuthHeader) == 0 { | ||
return nil, errors.Err("access forbidden").WithStatus(http.StatusForbidden) | ||
} | ||
|
||
payload, err := idtoken.Validate(r.Context(), splitAuthHeader[1], "") | ||
if err != nil { | ||
// invalid token | ||
return nil, errors.Err("access forbidden").WithStatus(http.StatusForbidden) | ||
} | ||
|
||
if payload.Issuer != "accounts.google.com" && payload.Issuer != "https://accounts.google.com" { | ||
return nil, errors.Err("access forbidden").WithStatus(http.StatusForbidden) | ||
} | ||
|
||
if payload.Claims == nil { | ||
return nil, errors.Err("access forbidden").WithStatus(http.StatusForbidden) | ||
} | ||
|
||
if emailVerified := payload.Claims["email_verified"].(bool); !emailVerified && payload.Claims["email_verified"] != "true" { | ||
return nil, errors.Err("access forbidden").WithStatus(http.StatusForbidden) | ||
} | ||
|
||
if payload.Claims["email"] != m.ServiceAccount { | ||
return nil, errors.Err("access forbidden").WithStatus(http.StatusForbidden) | ||
} | ||
|
||
return h.Serve(w, r) | ||
}) | ||
} | ||
|
||
const securitySchemeKey = "gcloud_service_account" | ||
|
||
// Doc implements the openapi.Documented interface | ||
func (m GCloudServiceAccount) Doc(builder *openapi.DocBuilder) error { | ||
_, ok := builder.Reflector(). | ||
SpecEns(). | ||
ComponentsEns(). | ||
SecuritySchemesEns(). | ||
MapOfSecuritySchemeOrRefValues[securitySchemeKey] | ||
|
||
if !ok { | ||
openIDScheme := new(openapi3.SecurityScheme). | ||
WithOpenIDConnectSecurityScheme( | ||
*new(openapi3.OpenIDConnectSecurityScheme). | ||
WithDescription(` | ||
This auth middleware is useful for endpoint called by a GCloud service for example: | ||
- Cloud Scheduler: https://cloud.google.com/scheduler/docs/http-target-auth | ||
- Pub/Sub: https://cloud.google.com/pubsub/docs/push#authentication | ||
`), | ||
) | ||
|
||
authSchema := *new(openapi3.SecuritySchemeOrRef).WithSecurityScheme(*openIDScheme) | ||
builder.Reflector(). | ||
SpecEns(). | ||
ComponentsEns(). | ||
SecuritySchemesEns(). | ||
WithMapOfSecuritySchemeOrRefValuesItem( | ||
securitySchemeKey, | ||
authSchema, | ||
) | ||
} | ||
|
||
builder.Operation(). | ||
WithSecurity(map[string][]string{ | ||
securitySchemeKey: { | ||
m.ServiceAccount, | ||
}, | ||
}) | ||
|
||
return nil | ||
} |
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,9 @@ | ||
module github.com/mwm-io/gapi-addons/gcloud/middleware/auth | ||
|
||
go 1.16 | ||
|
||
require ( | ||
github.com/mwm-io/gapi v0.0.1 | ||
github.com/swaggest/openapi-go v0.2.26 | ||
google.golang.org/api v0.103.0 | ||
) |
Oops, something went wrong.