Skip to content

Commit 8ab2e45

Browse files
author
Johannes Duesing
committed
Update documentation (swagger and readme). Some minor codestyle issues cleaned up.
1 parent fb5edde commit 8ab2e45

File tree

5 files changed

+147
-81
lines changed

5 files changed

+147
-81
lines changed

OpenAPISpecification.yaml

Lines changed: 100 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,87 @@ tags:
2020
containers
2121
- name: Docker Operations
2222
description: Operations on instances that are running in a docker container
23+
- name: User Management
24+
description: Operations related to the user database of Delphi-Management
2325
schemes:
2426
- https
2527
- http
2628
paths:
29+
/users/authenticate:
30+
post:
31+
tags:
32+
- User Management
33+
summary: Authenticates a user and returns a valid JWT
34+
description: >-
35+
This endpoints validates the username and password that must
36+
be supplied in the Authorization header (using HTTP Basic Authentication).
37+
If valid, a JSON Web Token will be generated and returned, that may be used
38+
to authenticate the user for subsequent requests.
39+
operationId: authenticate
40+
parameters:
41+
- in: header
42+
name: Delphi-Authorization
43+
description: >-
44+
Valid JWT that autenticates the calling entity.
45+
type: string
46+
required: true
47+
- in: header
48+
name: Authorization
49+
description: >-
50+
HTTP Basic Authentication following the schema 'Basic <User:Password>
51+
where the concatination of username and password is Base64-Encoded.
52+
type: string
53+
required: true
54+
responses:
55+
'200':
56+
description: Supplied data is valid, a JWT is returned
57+
schema:
58+
type: string
59+
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
60+
'401':
61+
description: Unauthorized, invalid username / password supplied.
62+
/users/add:
63+
post:
64+
tags:
65+
- User Management
66+
summary: Adds a new users for the registry
67+
description: >-
68+
Adds a new user that is passed in the requests entity. The id of the user
69+
will be returned.
70+
operationId: addUser
71+
parameters:
72+
- in: body
73+
name: DelphiUser
74+
description: The user to add
75+
required: true
76+
schema:
77+
type: object
78+
required:
79+
- userName
80+
- secret
81+
- userType
82+
properties:
83+
userName:
84+
type: string
85+
example: MyUser
86+
secret:
87+
type: string
88+
example: 123Pass
89+
userType:
90+
type: string
91+
enum:
92+
- Admin
93+
- User
94+
- Component
95+
responses:
96+
'200':
97+
description: OK, user has been added, id is returned
98+
schema:
99+
type: integer
100+
format: int64
101+
example: 42
102+
'400':
103+
description: Bad request, name already exists
27104
/instances/register:
28105
post:
29106
tags:
@@ -374,12 +451,15 @@ paths:
374451
description: 'Bad request, your label exceeded the character limit'
375452
'404':
376453
description: 'Not found, the id you specified could not be found'
377-
/instances/{Id}/logs:
454+
'/instances/{Id}/logs':
378455
get:
379456
tags:
380457
- Basic Operations
381458
summary: Retrieve the logging output of the specified instance
382-
description: This command retrieves the docker container logging output for the specified instance, if the instance is in fact running inside a docker container.
459+
description: >-
460+
This command retrieves the docker container logging output for the
461+
specified instance, if the instance is in fact running inside a docker
462+
container.
383463
operationId: retreiveLogs
384464
parameters:
385465
- name: Id
@@ -395,22 +475,28 @@ paths:
395475
type: boolean
396476
responses:
397477
'200':
398-
description: Success, log string is being returned
478+
description: 'Success, log string is being returned'
399479
schema:
400480
type: string
401-
example: "I am logging output .."
481+
example: I am logging output ..
402482
'400':
403483
description: Selected instance not running inside docker container
404484
'404':
405485
description: Id not found on the server
406486
'500':
407487
description: Internal Server Error
408-
/instances/{Id}/attach:
488+
'/instances/{Id}/attach':
409489
get:
410490
tags:
411491
- Basic Operations
412492
summary: Stream logging output from instance
413-
description: 'This command streams the docker container logging output for the specified instance. NOTE: This is a websocket endpoint, so only valid websocket requests will be processed. Swagger does not provide sufficient support for websockets, so this documentation might be confusing as it defines a HTTP method, etc. The names of parameters and response-codes are valid though.'
493+
description: >-
494+
This command streams the docker container logging output for the
495+
specified instance. NOTE: This is a websocket endpoint, so only valid
496+
websocket requests will be processed. Swagger does not provide
497+
sufficient support for websockets, so this documentation might be
498+
confusing as it defines a HTTP method, etc. The names of parameters and
499+
response-codes are valid though.
414500
operationId: streamLogs
415501
parameters:
416502
- name: Id
@@ -426,7 +512,7 @@ paths:
426512
type: boolean
427513
responses:
428514
'200':
429-
description: Success, logs are being streamed via websocket connection.
515+
description: 'Success, logs are being streamed via websocket connection.'
430516
'400':
431517
description: Selected instance not running inside docker container
432518
'404':
@@ -747,13 +833,12 @@ paths:
747833
description: One of the ids was not found on the server
748834
'500':
749835
description: Internal server error
750-
/instances/{Id}/command:
836+
'/instances/{Id}/command':
751837
post:
752838
tags:
753839
- Docker Operations
754840
summary: Runs a command into a docker container
755-
description: >-
756-
This command runs a specified command inside a docker container.
841+
description: This command runs a specified command inside a docker container.
757842
operationId: command
758843
parameters:
759844
- in: path
@@ -773,23 +858,21 @@ paths:
773858
properties:
774859
Command:
775860
type: string
776-
example: "rm -rf *"
861+
example: rm -rf *
777862
Privileged:
778863
type: boolean
779864
User:
780865
type: string
781866
example: root
782867
responses:
783868
'200':
784-
description: 'OK'
869+
description: OK
785870
'400':
786-
description: >-
787-
Cannot run command, ID is no docker container.
871+
description: 'Cannot run command, ID is no docker container.'
788872
'404':
789-
description: Cannot run command, ID not found.
873+
description: 'Cannot run command, ID not found.'
790874
'500':
791-
description: Internal server error, unknown operation result DESCRIPTION
792-
875+
description: 'Internal server error, unknown operation result DESCRIPTION'
793876
definitions:
794877
InstanceLink:
795878
type: object

README.md

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,19 @@ Before you can start the application, you have to make sure your configuration f
6060
|```dockerOperationTimeout``` | ```Timeout``` | ```Timeout(20 seconds)``` | Default timeout for docker operations. If any of the async Docker operations (deploy, stop, pause, ..) takes longer than this, it will be aborted.|
6161
|```defaultDockerUri``` | ```String``` | ```http://localhost:9095``` | Default uri to connect to docker. It will be used if the environment variable ```DELPHI_DOCKER_HOST``` is not specified.|
6262
|```jwtSecretKey``` | ```String``` | ```changeme``` | Secret key to use for JWT signature (HS256). This setting can be overridden by specifying the ```JWT_SECRET``` environment variable.|
63-
|```useInMemoryDB``` | ```Boolean``` | ```true``` | If set to true, all instance data will be kept in memory instead of using a MySQL database.|
64-
|```databaseHost``` | ```String``` | ```"jdbc:mysql://localhost/"``` | Host that the MySQL database is reachable at (only necessary if *useInMemoryDB* is false).|
65-
|```databaseName``` | ```String``` | ```""``` | Name of the MySQL database to use (only necessary if *useInMemoryDB* is false).|
66-
|```databaseDriver``` | ```String``` | ```"com.mysql.jdbc.Driver"``` | Driver to use for the MySQL connection (only necessary if *useInMemoryDB* is false).|
67-
|```databaseUsername``` | ```String``` | ```""``` | Username to use for the MySQL connection (only necessary if *useInMemoryDB* is false).|
68-
|```databasePassword``` | ```String``` | ```""``` | Password to use for the MySQL connection (only necessary if *useInMemoryDB* is false).|
63+
|```useInMemoryInstanceDB``` | ```Boolean``` | ```true``` | If set to true, all instance data will be kept in memory instead of using a MySQL database.|
64+
|```instanceDatabaseHost``` | ```String``` | ```"jdbc:mysql://localhost/"``` | Host that the MySQL instance database is reachable at (only necessary if *useInMemoryInstanceDB* is false).|
65+
|```instanceDatabaseName``` | ```String``` | ```""``` | Name of the MySQL instance database to use (only necessary if *useInMemoryInstanceDB* is false).|
66+
|```instanceDatabaseDriver``` | ```String``` | ```"com.mysql.jdbc.Driver"``` | Driver to use for the MySQL connection (only necessary if *useInMemoryInstanceDB* is false).|
67+
|```instanceDatabaseUsername``` | ```String``` | ```""``` | Username to use for the MySQL instance DB connection (only necessary if *useInMemoryInstanceDB* is false).|
68+
|```instanceDatabasePassword``` | ```String``` | ```""``` | Password to use for the MySQL instance DB connection (only necessary if *useInMemoryInstanceDB* is false).|
69+
|```useInMemoryAuthDB``` | ```Boolean``` | ```true``` | If set to true, all user data will be kept in memory instead of using a MySQL database.|
70+
|```authDatabaseHost``` | ```String``` | ```"jdbc:mysql://localhost/"``` | Host that the MySQL users database is reachable at (only necessary if *useInMemoryAuthDB* is false).|
71+
|```authDatabaseName``` | ```String``` | ```""``` | Name of the MySQL user database to use (only necessary if *useInMemoryAuthDB* is false).|
72+
|```authDatabaseDriver``` | ```String``` | ```"com.mysql.jdbc.Driver"``` | Driver to use for the MySQL users DB connection (only necessary if *useInMemoryAuthDB* is false).|
73+
|```authDatabaseUsername``` | ```String``` | ```""``` | Username to use for the MySQL users DB connection (only necessary if *useInMemoryAuthDB* is false).|
74+
|```authDatabasePassword``` | ```String``` | ```""``` | Password to use for the MySQL users DB connection (only necessary if *useInMemoryAuthDB* is false).|
75+
|```authenticationValidFor``` | ```Int``` | ```30``` | Default duration that user tokens are valid for (in minutes).|
6976
|```maxTotalNoRequest``` | ```Int``` | ```2000``` | Maximum number of requests that are allowed to be executed during the current refresh period regardless of their origin.|
7077
|```maxIndividualIpReq``` | ```Int``` | ```200``` | Maximum number of requests that are allowed to be executed during the current refresh period for one specific origin ip.|
7178
|```ipLogRefreshRate``` | ```FiniteDuration``` | ```2.minutes``` | Duration of the log refresh period.|

src/main/scala/de/upb/cs/swt/delphi/instanceregistry/connection/Server.scala

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
package de.upb.cs.swt.delphi.instanceregistry.connection
22

33
import akka.actor.ActorSystem
4-
import akka.http.scaladsl.server.RequestContext
54
import akka.http.scaladsl.model.ws.{Message, TextMessage}
6-
import akka.http.scaladsl.model.{HttpHeader, HttpResponse, StatusCodes}
5+
import akka.http.scaladsl.model.{HttpResponse, StatusCodes}
76
import akka.http.scaladsl.server
87
import akka.http.scaladsl.server.{HttpApp, Route}
98
import akka.stream.ActorMaterializer
109
import akka.stream.scaladsl.{Flow, Sink, Source}
1110
import de.upb.cs.swt.delphi.instanceregistry.authorization.AccessTokenEnums.UserType
12-
import de.upb.cs.swt.delphi.instanceregistry.authorization.{AccessToken, AuthProvider}
11+
import de.upb.cs.swt.delphi.instanceregistry.authorization.AccessToken
1312
import de.upb.cs.swt.delphi.instanceregistry.io.swagger.client.model.InstanceEnums.ComponentType
1413
import de.upb.cs.swt.delphi.instanceregistry.io.swagger.client.model._
1514
import de.upb.cs.swt.delphi.instanceregistry.requestLimiter.{IpLogActor, RequestLimitScheduler}
@@ -25,7 +24,7 @@ import scala.util.{Failure, Success, Try}
2524
*/
2625
class Server(handler: RequestHandler) extends HttpApp
2726
with InstanceJsonSupport
28-
with RequestJsonSupport
27+
with UserJsonSupport
2928
with EventJsonSupport
3029
with InstanceLinkJsonSupport
3130
with AppLogging {
@@ -135,16 +134,17 @@ class Server(handler: RequestHandler) extends HttpApp
135134
entity(as[String]) {
136135
jsonString => addUser(jsonString)
137136
}
137+
} ~
138+
path("authenticate") {
139+
authenticate()
138140
}
139141
}~
140142
path("events") {
141143
streamEvents()
142-
} ~
143-
path("authenticate") {
144-
authenticate()
145144
}
146145

147146

147+
148148
/**
149149
* Registers a new instance at the registry. This endpoint is intended for instances that are not running inside
150150
* a docker container, as the Id, DockerId and InstanceState are being ignored.
@@ -1093,20 +1093,23 @@ class Server(handler: RequestHandler) extends HttpApp
10931093
}
10941094

10951095
def authenticate() : server.Route = {
1096-
headerValueByName("Delphi-Authorization") { token =>
1097-
log.info(s"Requested with Delphi-Authorization token $token")
1098-
if(handler.authProvider.isValidDelphiToken(token)){
1099-
log.info(s"valid delphi authorization token")
1100-
authenticateBasic(realm = "secure", handler.authProvider.authenticateBasicJWT) {
1101-
case userName =>
1102-
complete(handler.authProvider.generateJwt(userName))
1103-
case _ =>
1104-
complete{HttpResponse(StatusCodes.InternalServerError, entity = s"Internal server error, unknown operation result")}
1096+
post
1097+
{
1098+
headerValueByName("Delphi-Authorization") { token =>
1099+
log.info(s"Requested with Delphi-Authorization token $token")
1100+
if(handler.authProvider.isValidDelphiToken(token)){
1101+
log.info(s"valid delphi authorization token")
1102+
authenticateBasic(realm = "secure", handler.authProvider.authenticateBasicJWT) {
1103+
case userName =>
1104+
complete(handler.authProvider.generateJwt(userName))
1105+
case _ =>
1106+
complete{HttpResponse(StatusCodes.InternalServerError, entity = s"Internal server error, unknown operation result")}
1107+
}
1108+
} else {
1109+
complete{HttpResponse(StatusCodes.Unauthorized, entity = s"Not valid Delphi-authorization")}
11051110
}
1106-
} else {
1107-
complete{HttpResponse(StatusCodes.Unauthorized, entity = s"Not valid Delphi-authorization")}
1108-
}
11091111

1112+
}
11101113
}
11111114
}
11121115

@@ -1126,7 +1129,7 @@ class Server(handler: RequestHandler) extends HttpApp
11261129
}
11271130
case Failure(ex) =>
11281131
log.error(ex, "Failed to handle registration of instance.")
1129-
complete(HttpResponse(StatusCodes.InternalServerError, entity = "An internal server error occurred."))
1132+
complete(HttpResponse(StatusCodes.BadRequest, entity = "Username already taken."))
11301133
}
11311134
} catch {
11321135
case dx: DeserializationException =>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package de.upb.cs.swt.delphi.instanceregistry.io.swagger.client.model
2+
3+
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
4+
import spray.json.{DefaultJsonProtocol, JsonFormat}
5+
6+
trait UserJsonSupport extends SprayJsonSupport with DefaultJsonProtocol{
7+
implicit val AuthDelphiUserFormat: JsonFormat[DelphiUser] = jsonFormat4(DelphiUser)
8+
}
9+
10+
final case class DelphiUser(id: Option[Long], userName: String, secret: String, userType: String)
11+

src/main/scala/de/upb/cs/swt/delphi/instanceregistry/io/swagger/client/model/RequestJsonSupport.scala

Lines changed: 0 additions & 38 deletions
This file was deleted.

0 commit comments

Comments
 (0)