Skip to content

stanislawbartkowski/MockRestService

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

73 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MockRestService

A simple solution to mock network traffic as HTTP POST/GET request. It is also an example of utilizing simple RestService library. https://github.com/stanislawbartkowski/RestService

Can be easily extended to more HTTP methods.

The solution is provided as two Intellij Idea projects: the server and the client. The server is a standalone Java application, the only prerequisite is RestService library mentioned above.It does not require any web server container like Tomcat or Jetty.

The client is Python 3 script.

Server

Installation

Download and install RestService to the local Maven repository.
https://github.com/stanislawbartkowski/RestService

git clone git clone https://github.com/stanislawbartkowski/MockRestService.git
mvn clean package
ls target

MockRestService-1.0-SNAPSHOT.jar
MockRestService-1.0-SNAPSHOT-jar-with-dependencies.jar

Run HTTP non-secure MockRest server

cp template/runserver.sh .

PORT=9800
java -cp target/MockRestService-1.0-SNAPSHOT-jar-with-dependencies.jar com.org.mockrestservice.MockRestService $POR

The only configuration is to specify the port number (here 9800).

./runserver.sh

Feb 29, 2020 7:42:20 PM com.rest.restservice.RestLogger info
INFO: Start HTTP Server, listening on port 9800
Feb 29, 2020 7:42:20 PM com.rest.restservice.RestLogger info
INFO: Register service: resetcounter
Feb 29, 2020 7:42:20 PM com.rest.restservice.RestLogger info
INFO: Register service: counter
Feb 29, 2020 7:42:20 PM com.rest.restservice.RestLogger info
INFO: Register service: rest
Feb 29, 2020 7:42:20 PM com.rest.restservice.RestLogger info
INFO: Register service: upload

The server is ready.

Test

  • POST request

curl -X POST http://localhost:9800/rest?content=Hello

  • Upload

curl -X POST -d Hello http://localhost:9800/upload

There is an internal counter scoring the number of POST "rest" requests received

  • Reset counter

curl -X GET http://localhost:9800/resetcounter

  • The current value of the counter

curl -X GET http://localhost:9800/counter

Run HTTPS secure MockRest server

Configuration

Copy and customize template/secure.properties file containing data for server certificates.

Variable Description Example
store.key.filename Pathname of the server key file cert/mykey.keystore
key.store.password Password protecting key file secret
alias Alias of the server certificate in the key file alias

In the runserver.sh script file uncomment the setting of SECURITY variable. The variable should point to secure.properties file.

Self-signed certificate

Example command to prepare self-signed certificate. Pay attention to proper key bit size.

keytool -genkey -alias alias -keypass secret -keystore mykey.keystore -storepass secret -keyalg rsa -keysize 2048

Test, -k switches off the certificate validation

curl -X POST https://localhost:9800/rest?content=Hello -k

Server certificate requested by CSR file

Generate self-signed certiticate

keytool -genkey -alias alias -keypass secret -keystore mykey.keystore -storepass secret -keyalg rsa -keysize 2048

Generate CSR file

keytool -certreq -keyalg RSA -alias alias -file certreq.csr -keystore mykey.keystore -keyalg rsa -keysize 2048

Send CSR file to CA center for signing.
Important: In case of authority certificate chain, it is necessary to import all certificates in the chain separately one after one. Otherwise, while importing the server certificate it will fail with "Failed to establish chain from reply."

Import root certificate

keytool -import -alias root -keystore mykey.keystore -file root.cert.pem

Import intermediate certificate

keytool -import -alias intermediate -keystore mykey.keystore -file intermediate.cert.pem

Import server certificate

keytool -import -alias alias -keystore mykey.keystore -file root.cert.pem

Test with certificate validation. The hostname (thinkde.sb.com) shoud match the CN of the server certificate.

curl -X POST https://thinkde.sb.com:9800/rest?content=Hello --cacert ca-chain.cert.pem

Kerberos

MockRestService can be also protected by Kerberos power. In order to setup Kerberos authentication, both client and server need access to KDC/AD service.

Prepare service principal and keytab

Assume the MockRestService is installed on thinkde.sb.com host. Kerberos is FQN aware, it is important that hostname resolves to FQN. The service principal name should follow the pattern HTTP/<FQN host name>@<realm name>. Example here: HTTP/thinkde.sb.com@CENTOS.COM.REALM

kadmin

addprinc -randkey HTTP/thinkde.sb.com@CENTOS.COM.REALM
ktadd -k service.keytab HTTP/thinkde.sb.com@CENTOS.COM.REALM

Entry for principal HTTP/thinkde.sb.com@CENTOS.COM.REALM with kvno 3, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:service.keytab.
Entry for principal HTTP/thinkde.sb.com@CENTOS.COM.REALM with kvno 3, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:service.keytab.
kadmin:

Prepare JAAS file for MockRestService

JAAS file should contain server entry allowing passwordless service authentication.

server {
    com.sun.security.auth.module.Krb5LoginModule required
    doNotPrompt=true
    principal="HTTP/thinkde.sb.com@CENTOS.COM.REALM"
    useKeyTab=true
    keyTab="/home/sb/s/keytab/service.keytab"
    storeKey=true;
};

Enable MockRestService for Kerberos

In runserver.sh script configure and uncomment KERBEROS variable.

PORT=9800
#SECURITY=secure.properties
#SECURITY=
KERBEROS="-Djava.security.auth.login.config=$PWD/server_jaas.conf"
KERBEROSDEBUG=-Dsun.security.krb5.debug=true
java $KERBEROS $KERBEROSDEBUG -cp target/MockRestService-1.0-SNAPSHOT-jar-with-dependencies.jar com.org.mockrestservice.MockRestService $PORT $SECURITY

Run

./runserver.sh

May 07, 2020 12:34:48 PM com.rest.restservice.RestLogger info
INFO: Authenticated principal: [HTTP/thinkde.sb.com@CENTOS.COM.REALM]
May 07, 2020 12:34:48 PM com.rest.restservice.RestLogger info

Test client

Obtain Kerberos ticket. Use FQN in the URL to access the service.

kinit user1
curl --negotiate -u : -X POST http://thinkde.sb.com:9800/rest?content=Hello

In the log server, watch the entry.

May 07, 2020 12:35:38 PM com.rest.restservice.RestLogger info
INFO: Authenticated as: user1@CENTOS.COM.REALM
May 07, 2020 12:35:38 PM com.rest.restservice.RestLogger info
INFO: POST content=Hello

Troubleshooting

Enable KERBEROSDEBUG in the runservice.sh script file giving more verbose output.
Add -v to curl command for more verbose output.

  • MockRestService seems to be stuck, do not response
    Make sure that /etc/krb5.conf contains entry.
[libdefaults]
..........
    udp_preference_limit = 1

  • Cannot access URL, in the server log there is an entry:
GSSException: No credential found for: 1.3.6.1.5.5.2 usage: Accept
	at sun.security.jgss.GSSCredentialImpl.getElement(GSSCredentialImpl.java:600)

or

message GSSException: Failure unspecified at GSS-API level (Mechanism level: Checksum failed)

On the client side, make sure that service ticket obtained contains FQN, not short hostname.

Correct:

 klist
Ticket cache: FILE:/tmp/krb5cc_1001
Default principal: user1@CENTOS.COM.REALM

Valid starting       Expires              Service principal
07.05.2020 12:18:25  08.05.2020 12:18:25  krbtgt/CENTOS.COM.REALM@CENTOS.COM.REALM
	renew until 07.05.2020 12:18:25
07.05.2020 12:26:48  08.05.2020 12:18:25  HTTP/thinkde.sb.com@CENTOS.COM.REALM
	renew until 07.05.2020 12:18:25

Wrong:

klist
Ticket cache: FILE:/tmp/krb5cc_1001
Default principal: user1@CENTOS.COM.REALM

Valid starting       Expires              Service principal
07.05.2020 12:18:25  08.05.2020 12:18:25  krbtgt/CENTOS.COM.REALM@CENTOS.COM.REALM
	renew until 07.05.2020 12:18:25
07.05.2020 12:26:48  08.05.2020 12:18:25  HTTP/thinkde@CENTOS.COM.REALM
	renew until 07.05.2020 12:18:25

It can happen if */etc/hosts* contains host short name first.
Wrong:
192.168.0.206	thinkde thinkde.sb.com 

Correct:

192.168.0.206	thinkde.sb.com thinkde

Client

Prerequisites

  • Python 3 (tested with Python 3.6 level)

yum install python36

  • requests package

yum install python36-pip
python36 -m pip install requests

Run unit test

Modify the hostname and the application name in Tomcat server.

cd MockRest/CallRest/test/rest
vi Test1.py

SERVERHOST="localhost:8080"
APPNAME="RestMockServer"

Run the test.

cd MockRest/CallRest/test/rest
PYTHONPATH=../.. python36 -m unittest Test1.py

/home/user/rest/MockRest/CallRest/test/rest/Test1.py:18: ResourceWarning: unclosed file <_io.TextIOWrapper name='/home/user/rest/MockRest/CallRest/com/rest/../../resource/f.txt' mode='r' encoding='UTF-8'>
  res = R.uploadFile("f.txt")
<html><head></head><body>File f.txt uploaded successfully.<br><a href="UploadDownloadFileServlet?fileName=f.txt">Download f.txt</a></body></html>
./home/user/rest/MockRest/CallRest/test/rest/Test1.py:22: ResourceWarning: unclosed file <_io.TextIOWrapper name='/home/user/rest/MockRest/CallRest/com/rest/../../resource/upgrade-error.txt' mode='r' encoding='UTF-8'>
  res = R.uploadFile("upgrade-error.txt")
<html><head></head><body>File upgrade-error.txt uploaded successfully.<br><a href="UploadDownloadFileServlet?fileName=upgrade-error.txt">Download upgrade-error.txt</a></body></html>
.received
.
----------------------------------------------------------------------
Ran 3 tests in 0.021s

OK

Run Rest/HTTP client

cd MockRest/CallRest
PYTHONPATH=. python36 com/MainRun.py

  • run.sh Single run
  • runattack.sh Launch a seriers of run.sh in parallel

Podman

Image and container

Create image and container. RestService is listening on 8080 port. You can specify different port if necessary.

podman build --build-arg RESTPORT=800 -t restmock .
podman run --name restmock -d -p 8080:8080 restmock

Make it public

podman tag restmock quay.io/stanislawbartkowski/restmock:latest
podman push quay.io/stanislawbartkowski/restmock:latest

Kubernetes, Openshift

if RESTPORT is less then 1000, create restmock-sa less restrictive Service Account to allow run pod as root privileged user.

oc create sa restmock-sa
oc adm policy add-scc-to-user anyuid -z restmock-sa

Modify restmock.yml

    spec:
      serviceAccountName: restmock-sa
      containers:
        - name: restmock

oc create -f restmock.yml

deployment.apps/restmock created
service/restmock created

Expose the service to external world.

oc expose scv/restmock


oc get routes

NAME        HOST/PORT                                   PATH   SERVICES    PORT           TERMINATION   WILDCARD
restmock    restmock-sb.apps.jobbery.cp.fyre.ibm.com           restmock    restmock-tcp                 None

Access the service.

curl -X POST http://restmock-sb.apps.jobbery.cp.fyre.ibm.com/rest?content=Hello

received (1)

Podman, secure service

Prepare configuration and keystore

Prepare sec directory containing parameter file and keystore with key and certificate.

ls sec

mykey.keystore  
secure.properties

cat sec/secure.properties

store.key.filename=/sec/mykey.keystore
key.store.password=secret

SELinux

If SELinux is enabled, create SE policy for sec directory to give container access to it.

semanage fcontext -a -t container_file_t '{dir}/sec(/.*)?'
restorecon -R {dir}/sec

Create image and container

Image.

podman build --build-arg RESTPORT=443 --build-arg SECURE="-s /sec/secure.properties" -t restmock-secure .

Container.

podman run --name restmock-secure -d -p 8443:443 -v {dir}/sec:/sec restmock-secure

Make it public

podman tag restmock-secure quay.io/stanislawbartkowski/restmock-secure:latest

podman push quay.io/stanislawbartkowski/restmock-secure:latest

Create secrets

Use configuration file and keystore prepared earlier.

oc create secret generic restmock-secret --from-file=sec/mykey.keystore --from-file=sec/secure.properties

Deploy to OpenShift

Use restmock-sa Service Account created before. The secrets are recreated in /sec pod directory.

oc create -f restmock-secure.yml

Create passthrough route

oc create route passthrough restmock-secure --service restmock-secure --port 443

oc get route

NAME              HOST/PORT                                         PATH   SERVICES          PORT           TERMINATION   WILDCARD
restmock-secure   restmock-secure-sb.apps.jobbery.cp.fyre.ibm.com          restmock-secure   443            passthrough   None

Access the service in secure way

curl -X POST https://restmock-secret-sb.apps.jobbery.cp.fyre.ibm.com/rest?content=Hello -k


About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published