Skip to content

Commit

Permalink
health: Introduce health and version endpoint
Browse files Browse the repository at this point in the history
Signed-off-by: arekkas <[email protected]>
  • Loading branch information
arekkas authored and arekkas committed Jul 21, 2018
1 parent c53f5b2 commit 029c7ff
Show file tree
Hide file tree
Showing 36 changed files with 884 additions and 163 deletions.
59 changes: 59 additions & 0 deletions cmd/helper_health.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright © 2017-2018 Aeneas Rekkas <[email protected]>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @author Aeneas Rekkas <[email protected]>
* @copyright 2017-2018 Aeneas Rekkas <[email protected]>
* @license Apache-2.0
*/

package cmd

import (
"github.com/julienschmidt/httprouter"
"github.com/ory/herodot"
"github.com/ory/oathkeeper/health"
)

type pinger interface {
Ping() error
}

func newHealthHandler(database interface{}, h *herodot.JSONWriter, router *httprouter.Router) *health.Handler {
var rc health.ReadyChecker

if database == nil {
rc = func() error {
return nil
}
} else {

switch con := database.(type) {
case pinger:
rc = func() error {
return con.Ping()
}
break
default:
panic("Unknown connection type.")
}

}

handler := health.NewHandler(h, Version, map[string]health.ReadyChecker{
"database": rc,
})

return handler
}
19 changes: 16 additions & 3 deletions cmd/helper_sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ func connectToSql(dburl string) (*sqlx.DB, error) {
return nil, errors.Errorf(`Unknown DSN "%s" in DATABASE_URL: %s`, u.Scheme, dburl)
}

func newRuleManager(dburl string) (rule.Manager, error) {
func connectToDatabase(dburl string) (interface{}, error) {
if dburl == "memory" {
return &rule.MemoryManager{Rules: map[string]rule.Rule{}}, nil
return nil, nil
} else if dburl == "" {
return nil, errors.New("No database URL provided")
}
Expand All @@ -61,5 +61,18 @@ func newRuleManager(dburl string) (rule.Manager, error) {
return nil, errors.WithStack(err)
}

return rule.NewSQLManager(db), nil
return db, nil
}

func newRuleManager(database interface{}) (rule.Manager, error) {
if database == nil {
return &rule.MemoryManager{Rules: map[string]rule.Rule{}}, nil
}

switch db := database.(type) {
case *sqlx.DB:
return rule.NewSQLManager(db), nil
default:
return nil, errors.New("Unknown database type")
}
}
9 changes: 8 additions & 1 deletion cmd/serve_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,12 @@ HTTP CONTROLS
` + corsMessage,
Run: func(cmd *cobra.Command, args []string) {
rules, err := newRuleManager(viper.GetString("DATABASE_URL"))
db, err := connectToDatabase(viper.GetString("DATABASE_URL"))
if err != nil {
logger.WithError(err).Fatalln("Unable to initialize database connectivity")
}

rules, err := newRuleManager(db)
if err != nil {
logger.WithError(err).Fatalln("Unable to connect to rule backend")
}
Expand All @@ -84,8 +89,10 @@ HTTP CONTROLS
))
keyHandler := rsakey.NewHandler(writer, keyManager)
router := httprouter.New()
health := newHealthHandler(db, writer, router)
ruleHandler.SetRoutes(router)
keyHandler.SetRoutes(router)
health.SetRoutes(router)

n := negroni.New()
n.Use(negronilogrus.NewMiddlewareFromLogger(logger, "oathkeeper-api"))
Expand Down
140 changes: 121 additions & 19 deletions docs/api.swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,51 @@
}
}
},
"/health/alive": {
"get": {
"description": "This endpoint returns a 200 status code when the HTTP server is up running.\nThis status does currently not include checks whether the database connection is working.\nThis endpoint does not require the `X-Forwarded-Proto` header when TLS termination is set.\n\nBe aware that if you are running multiple nodes of ORY Oathkeeper, the health status will never refer to the cluster state, only to a single instance.",
"tags": [
"health"
],
"summary": "Check the Alive Status",
"operationId": "isInstanceAlive",
"responses": {
"200": {
"description": "healthStatus",
"schema": {
"$ref": "#/definitions/healthStatus"
}
},
"500": {
"$ref": "#/responses/genericError"
}
}
}
},
"/health/ready": {
"get": {
"description": "This endpoint returns a 200 status code when the HTTP server is up running and the environment dependencies (e.g.\nthe database) are responsive as well.\n\nThis status does currently not include checks whether the database connection is working.\nThis endpoint does not require the `X-Forwarded-Proto` header when TLS termination is set.\n\nBe aware that if you are running multiple nodes of ORY Oathkeeper, the health status will never refer to the cluster state, only to a single instance.",
"tags": [
"health"
],
"summary": "Check the Readiness Status",
"operationId": "isInstanceReady",
"responses": {
"200": {
"description": "healthStatus",
"schema": {
"$ref": "#/definitions/healthStatus"
}
},
"503": {
"description": "healthNotReadyStatus",
"schema": {
"$ref": "#/definitions/healthNotReadyStatus"
}
}
}
}
},
"/rules": {
"get": {
"description": "This method returns an array of all rules that are stored in the backend. This is useful if you want to get a full\nview of what rules you have currently in place.",
Expand Down Expand Up @@ -283,6 +328,24 @@
}
}
}
},
"/version": {
"get": {
"description": "This endpoint returns the version as `{ \"version\": \"VERSION\" }`. The version is only correct with the prebuilt binary and not custom builds.",
"tags": [
"version"
],
"summary": "Get the version of Oathkeeper",
"operationId": "getVersion",
"responses": {
"200": {
"description": "version",
"schema": {
"$ref": "#/definitions/version"
}
}
}
}
}
},
"definitions": {
Expand All @@ -295,7 +358,7 @@
"x-go-name": "ClientID"
},
"scope": {
"description": "Scopes is an array of scopes that are required.",
"description": "Scope is an array of scopes that are required.",
"type": "array",
"items": {
"type": "string"
Expand All @@ -313,12 +376,12 @@
"type": "object",
"properties": {
"scope": {
"description": "Scopes is an array of scopes that are required.",
"description": "Scope is an array of scopes that are required.",
"type": "array",
"items": {
"type": "string"
},
"x-go-name": "Scopes"
"x-go-name": "Scope"
},
"token": {
"description": "Token is the token to introspect.",
Expand Down Expand Up @@ -386,6 +449,10 @@
"type": "string",
"x-go-name": "Subject"
},
"token_type": {
"type": "string",
"x-go-name": "TokenType"
},
"username": {
"type": "string",
"x-go-name": "Username"
Expand Down Expand Up @@ -439,7 +506,7 @@
"type": "boolean",
"x-go-name": "Allowed"
},
"subject": {
"sub": {
"description": "Subject is the identity that authorized issuing the token, for example a user or an OAuth2 app.\nThis is usually a uuid but you can choose a urn or some other id too.",
"type": "string",
"x-go-name": "Subject"
Expand All @@ -456,7 +523,7 @@
"type": "boolean",
"x-go-name": "Allowed"
},
"subject": {
"sub": {
"description": "Subject is the identity that authorized issuing the token, for example a user or an OAuth2 app.\nThis is usually a uuid but you can choose a urn or some other id too.",
"type": "string",
"x-go-name": "Subject"
Expand All @@ -473,7 +540,7 @@
"type": "boolean",
"x-go-name": "Allowed"
},
"audience": {
"aud": {
"type": "array",
"items": {
"type": "string"
Expand All @@ -485,36 +552,33 @@
"type": "string",
"x-go-name": "ClientID"
},
"expires_at": {
"exp": {
"description": "ExpiresAt is the expiry timestamp.",
"type": "string",
"format": "date-time",
"x-go-name": "ExpiresAt"
},
"granted_scope": {
"description": "GrantedScopes is a list of scopes that the subject authorized when asked for consent.",
"type": "array",
"items": {
"type": "string"
},
"x-go-name": "GrantedScopes"
},
"issued_at": {
"iat": {
"description": "IssuedAt is the token creation time stamp.",
"type": "string",
"format": "date-time",
"x-go-name": "IssuedAt"
},
"issuer": {
"iss": {
"description": "Issuer is the id of the issuer, typically an hydra instance.",
"type": "string",
"x-go-name": "Issuer"
},
"not_before": {
"nbf": {
"type": "string",
"format": "date-time",
"x-go-name": "NotBefore"
},
"scope": {
"description": "GrantedScopes is a list of scopes that the subject authorized when asked for consent.",
"type": "string",
"x-go-name": "GrantedScopes"
},
"session": {
"description": "Session represents arbitrary session data.",
"type": "object",
Expand All @@ -523,7 +587,7 @@
},
"x-go-name": "Extra"
},
"subject": {
"sub": {
"description": "Subject is the identity that authorized issuing the token, for example a user or an OAuth2 app.\nThis is usually a uuid but you can choose a urn or some other id too.",
"type": "string",
"x-go-name": "Subject"
Expand All @@ -536,6 +600,33 @@
"x-go-name": "OAuth2Session",
"x-go-package": "github.com/ory/oathkeeper/vendor/github.com/ory/keto/authentication"
},
"healthNotReadyStatus": {
"type": "object",
"properties": {
"errors": {
"description": "Errors contains a list of errors that caused the not ready status.",
"type": "object",
"additionalProperties": {
"type": "string"
},
"x-go-name": "Errors"
}
},
"x-go-name": "swaggerNotReadyStatus",
"x-go-package": "github.com/ory/oathkeeper/health"
},
"healthStatus": {
"type": "object",
"properties": {
"status": {
"description": "Status always contains \"ok\".",
"type": "string",
"x-go-name": "Status"
}
},
"x-go-name": "swaggerHealthStatus",
"x-go-package": "github.com/ory/oathkeeper/health"
},
"jsonWebKey": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -790,6 +881,17 @@
}
},
"x-go-package": "github.com/ory/oathkeeper/rule"
},
"version": {
"type": "object",
"properties": {
"version": {
"type": "string",
"x-go-name": "Version"
}
},
"x-go-name": "swaggerVersion",
"x-go-package": "github.com/ory/oathkeeper/health"
}
},
"responses": {
Expand Down
Loading

0 comments on commit 029c7ff

Please sign in to comment.