feat: Added auth token server

issue #96
This commit is contained in:
Andrey Melnikov
2020-03-10 12:53:13 -07:00
parent 8a3306f4df
commit c5975a4022
9 changed files with 174 additions and 216 deletions

View File

@@ -21,6 +21,32 @@
"application/json"
],
"paths": {
"/apis/v1beta1/auth/token": {
"post": {
"operationId": "IsValidToken",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/IsValidTokenResponse"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/Token"
}
}
],
"tags": [
"AuthService"
]
}
},
"/apis/v1beta1/namespaces": {
"get": {
"operationId": "ListNamespaces",
@@ -30,12 +56,6 @@
"schema": {
"$ref": "#/definitions/ListNamespacesResponse"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"tags": [
@@ -52,12 +72,6 @@
"schema": {
"$ref": "#/definitions/ListSecretsResponse"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"parameters": [
@@ -80,12 +94,6 @@
"schema": {
"properties": {}
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"parameters": [
@@ -118,12 +126,6 @@
"schema": {
"$ref": "#/definitions/Secret"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"parameters": [
@@ -152,12 +154,6 @@
"schema": {
"$ref": "#/definitions/DeleteSecretResponse"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"parameters": [
@@ -188,12 +184,6 @@
"schema": {
"$ref": "#/definitions/SecretExistsResponse"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"parameters": [
@@ -224,12 +214,6 @@
"schema": {
"$ref": "#/definitions/AddSecretKeyValueResponse"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"parameters": [
@@ -266,12 +250,6 @@
"schema": {
"$ref": "#/definitions/UpdateSecretKeyValueResponse"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"parameters": [
@@ -310,12 +288,6 @@
"schema": {
"$ref": "#/definitions/DeleteSecretKeyResponse"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"parameters": [
@@ -352,12 +324,6 @@
"schema": {
"$ref": "#/definitions/ListWorkflowExecutionsResponse"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"parameters": [
@@ -399,6 +365,7 @@
]
},
"post": {
"summary": "Creates a Workflow",
"operationId": "CreateWorkflowExecution",
"responses": {
"200": {
@@ -406,12 +373,6 @@
"schema": {
"$ref": "#/definitions/WorkflowExecution"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"parameters": [
@@ -444,12 +405,6 @@
"schema": {
"$ref": "#/definitions/WorkflowExecution"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"parameters": [
@@ -480,12 +435,6 @@
"schema": {
"$ref": "#/definitions/ArtifactResponse"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"parameters": [
@@ -522,12 +471,6 @@
"schema": {
"$ref": "#/definitions/ListFilesResponse"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"parameters": [
@@ -562,22 +505,7 @@
"200": {
"description": "A successful response.(streaming responses)",
"schema": {
"type": "object",
"properties": {
"result": {
"$ref": "#/definitions/LogEntry"
},
"error": {
"$ref": "#/definitions/grpc.gateway.runtime.StreamError"
}
},
"title": "Stream result of LogEntry"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
"$ref": "#/x-stream-definitions/LogEntry"
}
}
},
@@ -621,12 +549,6 @@
"schema": {
"$ref": "#/definitions/GetWorkflowExecutionMetricsResponse"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"parameters": [
@@ -663,12 +585,6 @@
"schema": {
"$ref": "#/definitions/WorkflowExecution"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"parameters": [
@@ -699,12 +615,6 @@
"schema": {
"properties": {}
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"parameters": [
@@ -733,22 +643,7 @@
"200": {
"description": "A successful response.(streaming responses)",
"schema": {
"type": "object",
"properties": {
"result": {
"$ref": "#/definitions/WorkflowExecution"
},
"error": {
"$ref": "#/definitions/grpc.gateway.runtime.StreamError"
}
},
"title": "Stream result of WorkflowExecution"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
"$ref": "#/x-stream-definitions/WorkflowExecution"
}
}
},
@@ -780,12 +675,6 @@
"schema": {
"$ref": "#/definitions/ListWorkflowTemplatesResponse"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"parameters": [
@@ -808,12 +697,6 @@
"schema": {
"$ref": "#/definitions/WorkflowTemplate"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"parameters": [
@@ -846,12 +729,6 @@
"schema": {
"$ref": "#/definitions/WorkflowTemplate"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"parameters": [
@@ -889,12 +766,6 @@
"schema": {
"$ref": "#/definitions/ArchiveWorkflowTemplateResponse"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"parameters": [
@@ -925,12 +796,6 @@
"schema": {
"$ref": "#/definitions/ListWorkflowTemplateVersionsResponse"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"parameters": [
@@ -961,12 +826,6 @@
"schema": {
"$ref": "#/definitions/WorkflowTemplate"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"parameters": [
@@ -1004,12 +863,6 @@
"schema": {
"$ref": "#/definitions/WorkflowTemplate"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"parameters": [
@@ -1048,12 +901,6 @@
"schema": {
"$ref": "#/definitions/WorkflowTemplate"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/grpc.gateway.runtime.Error"
}
}
},
"parameters": [
@@ -1175,6 +1022,15 @@
}
}
},
"IsValidTokenResponse": {
"type": "object",
"properties": {
"valid": {
"type": "boolean",
"format": "boolean"
}
}
},
"ListFilesResponse": {
"type": "object",
"properties": {
@@ -1333,6 +1189,14 @@
}
}
},
"Token": {
"type": "object",
"properties": {
"token": {
"type": "string"
}
}
},
"UpdateSecretKeyValueResponse": {
"type": "object",
"properties": {
@@ -1432,27 +1296,6 @@
},
"description": "`Any` contains an arbitrary serialized protocol buffer message along with a\nURL that describes the type of the serialized message.\n\nProtobuf library provides support to pack/unpack Any values in the form\nof utility functions or additional generated methods of the Any type.\n\nExample 1: Pack and unpack a message in C++.\n\n Foo foo = ...;\n Any any;\n any.PackFrom(foo);\n ...\n if (any.UnpackTo(&foo)) {\n ...\n }\n\nExample 2: Pack and unpack a message in Java.\n\n Foo foo = ...;\n Any any = Any.pack(foo);\n ...\n if (any.is(Foo.class)) {\n foo = any.unpack(Foo.class);\n }\n\n Example 3: Pack and unpack a message in Python.\n\n foo = Foo(...)\n any = Any()\n any.Pack(foo)\n ...\n if any.Is(Foo.DESCRIPTOR):\n any.Unpack(foo)\n ...\n\n Example 4: Pack and unpack a message in Go\n\n foo := &pb.Foo{...}\n any, err := ptypes.MarshalAny(foo)\n ...\n foo := &pb.Foo{}\n if err := ptypes.UnmarshalAny(any, foo); err != nil {\n ...\n }\n\nThe pack methods provided by protobuf library will by default use\n'type.googleapis.com/full.type.name' as the type URL and the unpack\nmethods only use the fully qualified type name after the last '/'\nin the type URL, for example \"foo.bar.com/x/y.z\" will yield type\nname \"y.z\".\n\n\nJSON\n====\nThe JSON representation of an `Any` value uses the regular\nrepresentation of the deserialized, embedded message, with an\nadditional field `@type` which contains the type URL. Example:\n\n package google.profile;\n message Person {\n string first_name = 1;\n string last_name = 2;\n }\n\n {\n \"@type\": \"type.googleapis.com/google.profile.Person\",\n \"firstName\": <string>,\n \"lastName\": <string>\n }\n\nIf the embedded message type is well-known and has a custom JSON\nrepresentation, that representation will be embedded adding a field\n`value` which holds the custom JSON in addition to the `@type`\nfield. Example (for message [google.protobuf.Duration][]):\n\n {\n \"@type\": \"type.googleapis.com/google.protobuf.Duration\",\n \"value\": \"1.212s\"\n }"
},
"grpc.gateway.runtime.Error": {
"type": "object",
"properties": {
"error": {
"type": "string"
},
"code": {
"type": "integer",
"format": "int32"
},
"message": {
"type": "string"
},
"details": {
"type": "array",
"items": {
"$ref": "#/definitions/google.protobuf.Any"
}
}
}
},
"grpc.gateway.runtime.StreamError": {
"type": "object",
"properties": {
@@ -1479,6 +1322,32 @@
}
}
},
"x-stream-definitions": {
"LogEntry": {
"type": "object",
"properties": {
"result": {
"$ref": "#/definitions/LogEntry"
},
"error": {
"$ref": "#/definitions/grpc.gateway.runtime.StreamError"
}
},
"title": "Stream result of LogEntry"
},
"WorkflowExecution": {
"type": "object",
"properties": {
"result": {
"$ref": "#/definitions/WorkflowExecution"
},
"error": {
"$ref": "#/definitions/grpc.gateway.runtime.StreamError"
}
},
"title": "Stream result of WorkflowExecution"
}
},
"securityDefinitions": {
"Bearer": {
"type": "apiKey",

27
api/auth.proto Normal file
View File

@@ -0,0 +1,27 @@
syntax = "proto3";
package api;
import "google/api/annotations.proto";
import "google/protobuf/empty.proto";
service AuthService {
rpc IsValidToken(IsValidTokenRequest) returns (IsValidTokenResponse) {
option (google.api.http) = {
post: "/apis/v1beta1/auth/token"
body: "token"
};
}
}
message IsValidTokenResponse {
bool valid = 1;
}
message IsValidTokenRequest {
Token token = 1;
}
message Token {
string token = 1;
}

View File

@@ -140,11 +140,11 @@ var fileDescriptor_ecb1e126f615f5dd = []byte{
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConnInterface
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion6
const _ = grpc.SupportPackageIsVersion4
// NamespaceServiceClient is the client API for NamespaceService service.
//
@@ -154,10 +154,10 @@ type NamespaceServiceClient interface {
}
type namespaceServiceClient struct {
cc grpc.ClientConnInterface
cc *grpc.ClientConn
}
func NewNamespaceServiceClient(cc grpc.ClientConnInterface) NamespaceServiceClient {
func NewNamespaceServiceClient(cc *grpc.ClientConn) NamespaceServiceClient {
return &namespaceServiceClient{cc}
}

View File

@@ -763,11 +763,11 @@ var fileDescriptor_6acf428160d7a216 = []byte{
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConnInterface
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion6
const _ = grpc.SupportPackageIsVersion4
// SecretServiceClient is the client API for SecretService service.
//
@@ -784,10 +784,10 @@ type SecretServiceClient interface {
}
type secretServiceClient struct {
cc grpc.ClientConnInterface
cc *grpc.ClientConn
}
func NewSecretServiceClient(cc grpc.ClientConnInterface) SecretServiceClient {
func NewSecretServiceClient(cc *grpc.ClientConn) SecretServiceClient {
return &secretServiceClient{cc}
}

View File

@@ -1159,11 +1159,11 @@ var fileDescriptor_892c7f566756b0be = []byte{
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConnInterface
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion6
const _ = grpc.SupportPackageIsVersion4
// WorkflowServiceClient is the client API for WorkflowService service.
//
@@ -1190,10 +1190,10 @@ type WorkflowServiceClient interface {
}
type workflowServiceClient struct {
cc grpc.ClientConnInterface
cc *grpc.ClientConn
}
func NewWorkflowServiceClient(cc grpc.ClientConnInterface) WorkflowServiceClient {
func NewWorkflowServiceClient(cc *grpc.ClientConn) WorkflowServiceClient {
return &workflowServiceClient{cc}
}

2
go.mod
View File

@@ -34,7 +34,7 @@ require (
github.com/mattn/go-sqlite3 v2.0.2+incompatible // indirect
github.com/minio/minio-go/v6 v6.0.45
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pkg/errors v0.9.1
github.com/pressly/goose v2.6.0+incompatible
github.com/sirupsen/logrus v1.4.2
github.com/spf13/cobra v0.0.5 // indirect

View File

@@ -114,6 +114,7 @@ func startHTTPProxy() {
registerHandler(api.RegisterWorkflowServiceHandlerFromEndpoint, ctx, mux, endpoint, opts)
registerHandler(api.RegisterSecretServiceHandlerFromEndpoint, ctx, mux, endpoint, opts)
registerHandler(api.RegisterNamespaceServiceHandlerFromEndpoint, ctx, mux, endpoint, opts)
registerHandler(api.RegisterAuthServiceHandlerFromEndpoint, ctx, mux, endpoint, opts)
log.Printf("Starting HTTP proxy on port %v", *httpPort)

View File

@@ -8,6 +8,24 @@ import (
var onepanelEnabledLabelKey = "onepanel.io/enabled"
func (c *Client) ListOnepanelEnabledNamespaces() (namespaces []*Namespace, err error) {
namespaceList, err := c.CoreV1().Namespaces().List(metav1.ListOptions{
LabelSelector: fmt.Sprintf("%s=%s", onepanelEnabledLabelKey, "true"),
})
if err != nil {
return
}
for _, ns := range namespaceList.Items {
namespaces = append(namespaces, &Namespace{
Name: ns.Name,
Labels: ns.Labels,
})
}
return
}
func (c *Client) ListNamespaces() (namespaces []*Namespace, err error) {
namespaceList, err := c.CoreV1().Namespaces().List(metav1.ListOptions{
LabelSelector: fmt.Sprintf("%s=%s", onepanelEnabledLabelKey, "true"),

43
server/auth_server.go Normal file
View File

@@ -0,0 +1,43 @@
package server
import (
"context"
"github.com/onepanelio/core/api"
v1 "github.com/onepanelio/core/pkg"
"github.com/onepanelio/core/server/auth"
"github.com/pkg/errors"
)
type AuthServer struct{}
func NewAuthServer() *AuthServer {
return &AuthServer{}
}
func (a *AuthServer) IsValidToken(ctx context.Context, req *api.IsValidTokenRequest) (*api.IsValidTokenResponse, error) {
client := ctx.Value("kubeClient").(*v1.Client)
namespaces, err := client.ListOnepanelEnabledNamespaces()
if err != nil {
return nil, err
}
if len(namespaces) == 0 {
return nil, errors.New("No namespaces for onepanel setup.")
}
namespace := namespaces[0]
allowed, err := auth.IsAuthorized(client, "", "get", "", "namespaces", namespace.Name)
if err != nil {
return nil, err
}
if !allowed {
return &api.IsValidTokenResponse{
Valid: false,
}, nil
}
return &api.IsValidTokenResponse{
Valid: true,
}, nil
}