Flink-ESB Tutorials
Short description: Create file repository offering storage and retrieval of files over HTTP(S). File repository should be able to handle very big files (>100 GB) without consuming of much RAM (working in stream mode).
Add security layer to manage read-only and read-write access using roles.
Example of usage: Application A produces files on hourly basis, for example report files containing customer data. Application B imports those files and processes them.
Problem: how to deliver files from Application A to Application B if there is no direct connectivity between server A and server B, or where server A and server B do now allow accessing their local folders from remote machines?
Solution: create a file repository. Application A would transfer files using HTTP(S) to the file repository. Application B would fetch the files from the file repository using HTTP(S). If needed, add security layer to administer access to the files and folders.
Following Flink-ESB components are used in this part of tutorial:
First level components:
HTTP Server : represents an instance of an empty HTTP server container. Add one or multiple "HTTP-Connectors" to create HTTP ports on that server instance.
HTTP Connector : used always together with "HTTP Server". Represents one port, where HTTP server accepts HTTP or HTTPS requests.
Resource Handler : used always together with "HTTP Server". Allows to access server's files and folders via HTTP.
Context : used always together with "HTTP Server". Used to configure server's security layer.
File Login Service : used always together with "Context" component. Used to set up security layer, where usernames/passwords/roles are stored in the file.
Open Flink-ESB Editor and select "File -> New -> Project" in the main menu. Double click "Flink-ESB" folder to expand it, select "Create New Flink-ESB Project" and press "Next"
This opens a "New Flink-ESB Project" wizard. Enter data as on picture below: "Project Name" : file-repository, unselect "Use default location" checkbox and select a folder where a project should be created:
Click "Next" and type some name in "Provider" field, after that click "Finish". This should create a new Flink-ESB project and open a file called "project.esbbp" in the main editor pane. This is where we will create all the components of the application.
Click on "HTTP Adapter" drawer on the components palette to the right of the main editor pain. Click on "HTTP Server" component, now move mouse pointer over editor canvas and click with the left mouse to put "HTTP Server" component onto canvas. Provide properties of the server as on picture below:
Click "Save Changes" to save Server's properties. Now select "HTTP Connector" within "HTTP Adapter" palette, and drop it onto editor canvas near "HTTP Server" component. Enter properties as on picture below:
Instead of configuring hard coded values for "Hostname" and "Port" properties, we could use project variables to make those properties configurable.
Avoid using hard coded values for environment variables or for performance relevant variables. See this tutorial to learn how to use project variables
Click "Save Changes" to save Connector's properties.
If you want this port to handle SSL (TLS) traffic, click on "SSL Parameters" tab in the properties window and provide needed properties.
Instead of configuring hard coded values for "Hostname" and "Port" properties, we could use project variables to make those properties configurable.
Avoid using hard coded values for environment variables or for performance relevant variables. See this tutorial to learn how to use project variables
Now we have defined HTTP server listening on port 4848. To try the server we have to start an application in Flink-ESB Editor. Select "Run" -> "Run Project in Test Mode" in main menu, or right click somewhere on editor canvas and select "Run Project in Test Mode", or click button in main toolbar to start a project.
If all goes well, you should see a green rectangle surrounding a project canvas. Otherwise an error message should give you a hint what could be wrong.
So far no resources were deployed on the server, so trying any URL on http://localhost:4848 would return HTTP 404 "Page not found" message:
Click on "HTTP Adapter" palette drawer to expand it, and place a "Resource Handler" component on editor canvas (scroll down within "HTTP Adapter" palette if you cannot see it). Enter properties as on picture below:
Click "Save Changes" to save Resource Handler's properties.
"Resource Handler" component allows HTTP access to the local folder. Path to the local folder is defined by "Location" property. "Context-Path" defines URI prefix to access resources within local folder.
Assuming a local folder d:\repository on your windows machine looks like on picture below:
Now try to access URL http://localhost:4848/repo. You should get a response as on picture below:
Now let's copy several files into folder d:\repository and refresh http://localhost:4848/repo in the browser. You should see now the files you've just copied to the folder:
Clcik on one of the folder's links to go into that folder and to view its content:
Go ahead and try reaching repository from another machine. Just make sure to use repository's IP instead of "localhost" in the URL. You should be able to view all the files and folders in the repository:
Select "Resource Handler" component in Flink-ESB Editor and adjust its properties as on picture below:
Setting property "Allow Modifications" to "true" enables WRITE operations on this "Resource Handler" component.
Click "Save Changes" and then save the project file. Restart the application.
Now go to the browser and refresh the page:
Now you should see 4 buttons on the top of the page to upload files, delete files, rename file and create folder. Also there is a checkbox on the left side of every file and folder.
Click "Create Folder" button in the browser. Enter a name of new folder, for example "test":
Click "Save" button and confirm a question in message box. A new folder must appear now. Check the local folder on repository machine to make sure the folder is created there.
Click on "test" folder to go into it. It must be empty.
Let us now upload some files in there. Click "Upload File(s)" button and select one or several files on some folder on your machine. Press "Upload" button. Now you should see all those files in the repository's folder:
Go to repository machine and verify that all those files exist in "test" subfolder within repository location.
Now let us rename one of the files. Select a checkbox beside one of the files. "Rename File" and "Delete File(s)" buttons should now be enabled. Click on "Rename File" button and modify a file name in the textbox:
Press "Save" button and confirm question in the message box. Now the name of the file must be modified:
Now try to delete files. Select checkbox for one or several files and press "Delete File(s)" button. Confirm a question in the message box. This should delete selected files:
Right now everybody who has access to your repository server via HTTP URL of your file repository can read, write and delete files and folders on the repository machine. Let us add security layer, so that only authenticated users will be able to access file repository.
Click on "HTTP Adapter" palette drawer to expand it, and place a "File Login Service" component on editor canvas (scroll down within "HTTP Adapter" palette if you cannot see it). Enter properties as on picture below:
"File" property points to a file, containing users data (username, password, roles). This file will be used to authenticate users trying to access HTTP server, that is defined in this application.
To create such file, open a new file in text editor and paste following content into it:
# The format is # username: password[,role] admin: admin,admin,user other: other,other username: password,user
Save this file with any name (for example: realm.properties), but make sure its name matches "File" property of "File Login Service" component.
Format of the file above is: username: password[,role1][,role2]...
So in the file above we've defined 3 users:
User 1 is called "admin", its password is "admin", and he is a member of 2 roles: "admin" and "user".
User 2 is called "other", its password is "other", and he is not a member of any roles.
User 3 is called "username", its password is "password", and he is a member of 1 role: "user".
!!! Avoid configuring passwords in clear text !!!
Flink-ESB provides command to encrypt/obfuscate/hash the password. Connect to SSH console of any Flink-ESB instance and run command: esb:app:password -u username password:
So for user "admin" configure obfuscated password instead of password in clear text: OBF:1u2a1toa1w8v1tok1u30
Instead of having all passwords in clear text, you can paste following content into "realm.properties" file:
# The format is # username: password[,role] admin: OBF:1u2a1toa1w8v1tok1u30,admin,user other: OBF:1xmk1w261u9r1w1c1xmq,other username: OBF:1v2j1uum1xtv1zej1zer1xtn1uvk1v1v,user
Add "Context" component from "HTTP Adapter" palette to the editor canvas. Set its properties as on picture below:
Property "Context-Path" has value "/repo". It means, all HTTP requests with URLs starting with "/repo" will be handled by this Context component.
Click "Save Changes" and then click on "Security" tab in the properties window. Enter the properties as on picture below:
Property "Authentication-Type" has value "DIGEST". It means, all HTTP requests to URLs protected by security layer, must send DIGEST HTTP Authentication header. Other possible values are "BASIC" and "FORM". You can try any of them in this tutorial.
Property "Login-Service-Ref" has value "file-login-service". It matches "ID" property of "File Login Service" component, which means username/password/roles data provided by "File Login Service" component will be used to authenticate all URLs handled by this "Context" component.
Click "Save Changes" and then click on "Security Constraints" tab in the properties window. Click "Add Constraint" button and enter properties as on picture below:
Only one security constraint for path "/.*" is defined here. This means all users accessing URLs, handled by this "Context" component, must be members of "user" role.
Full URL pattern for this constraint is concatenation of "Context-Path" property (which has value "/repo") and the value provided here. So it will be: /repo/.*
Click "Save Changes" to save Context's properties. Now select "HTTP Server" component in the editor and click on "Contexts" tab in the properties window. You should see one row with the context ID "repo-context". Select a checkbox beside that row:
This tells, that HTTP server will use "Context" component, whose "ID" property matches value "repo-context".
Click "Save Changes" and save the project file. Now restart the application in the editor.
Now when you go back to the browser and try to reach file repository, you are asked to enter username and password to authenticate:
Enter username as username and password as password. Now you should be able to see repository content:
Go ahead and try to login using admin as username and admin as password. Login should work as well.
We've defined login type as DIGEST (see above). With this login type browser keeps username/password information stored. So if you open a new window, it does not ask you to authenticate again, it uses authentication information from the previous login.
In order to try different username/password you must either clear the browser cache, or better start a new window in Inkognito mode. To do that using Google Chrome browser, press Ctrl+Shift+N. Now when you try to go to file repository URL, it should ask you to authenticate again.
But be aware: if you open the second window in Inkognito mode, it will reuse cache from the first Inkognito window. So if you want to try more username/password combinations, close Inkognito window, and open it again.
Try to access file repository using other as username and other as password. You should get HTTP 403 error:
Now try some non-existing (in your realm.properties file) credentials, for example test as username and test as password. You should also get HTTP 403 error.
Now let us create one additional level of security: READ-ONLY roles, and READ-WRITE roles. It means if you would login with the user, who is a member of READ-ONLY role, you should be able only to view repository's content. If you login with the user, who is member of READ-WRITE role, you should be able to view and modify the content of repository.
Select "Context" component in Flink-ESB Editor, click "Security Constraints" tab in the properties window and modify properties as on picture below:
Click "Save Changes". With that modification you define, that all users, that are members of either "user" or "admin" roles will be authorized to access file repository.
Now select "Resource Handler" component in the editor and modify its properties as on picture below:
Click "Save Changes". With that modification you define, that only members of "admin" group will be allowed to modify content of repository.
We've defined 2 roles to be able to access file repository: user and admin.
But only members of admin role can view and modify repository (READ-WRITE). Members of user role (who are not members of admin role at the same time) are allowed to view repository, but are not allowed to modify it (READ-ONLY).
Save project file and restart the application.
Now login into file repository using username as username, and password as password. You should get a response as on picture below:
As you can see, 4 buttons to modify repository are not visible, and also checkboxes on the left side of every file and folder have disappeared. So you are able to view the content, but not to modify it.
Now login using admin as username, and admin as password. You should get a response as on picture below:
Compare this picture with the previous one. With admin user you can view and modify the content of file repository.
As you have seen in the previous steps of this tutorial, with "Resource Handler" component you can access files and folders on the server over HTTP. You can upload new files onto the file repository using browser.
But what if you need to upload very big files? Using browser for that activity is not recommended, or even dangerous. You can end up will all your memory consumed by the browser. For such tasks use scripts, not the browser.
"Resource Handler" component offers out of the box API for such tasks. You can use any command which is able to send a content of file to the server with HTTP POST. Let us do that with curl command.
Create a big file on remote machine (if it does not exist yet). On Linux machine you can use this command to create a file of 10 GB size:
fallocate -l 10G test.img
To upload this file to remote file repository we can use following command:
curl -i -vvv --digest --user "admin:admin" -XPOST http://192.168.2.105:4848/repo/test/test.img --data-binary @test.img
Let us explain the meaning of all the parameters in the command above:
--digest --user "admin:admin" means, curl will try to authenticate using DIGEST authentication type (as we defined in our project). As user:password it will use admin:admin.
-XPOST means, curl will contact remote server using HTTP POST method.
http://192.168.2.105:4848/repo/test/test.img is URL, /test/test.img is relative path, where the file should be stored.
--data-binary @test.img tells curl to send content of "test.img" file in the body of HTTP POST call. Content should be transferred in binary mode.
This way you can upload files of any size to the remote file repository. Flink-ESB processes data in stream mode, which means, it does not consume much RAM, even if the file is huge. The only limitation is file space available on your file repository server.
Transferring 10 GB of data to remote server can take a while. After curl command is completed check the content of "test" subfolder within file repositoty. It should look like on picture below:
This proves, that the data transfer was successfully completed
When you transfer big files, there could be some network outages, or the script can be aborted manually. In this case only a part of the file is transferred to the file repository. Can we recognize such situations?
It is actually quite simple. Flink-ESB appends "__IN_TRANSFER__" to the file being transferred. Only after transfer is completed, it renames the file.
Let us verify this functionality. Create another big file with this command:
fallocate -l 5G test2.img
This creates a file with name "test2.img" and size of 5 GB. Now let us upload this file to remote file repository:
curl -i -vvv --digest --user "admin:admin" -XPOST http://192.168.2.105:4848/repo/test/test2.img --data-binary @test2.img
Run curl command, wait 1 or 2 minutes (transfer should be in progress), now press Ctrl+C to abort curl command execution.
Go to the browser and check the content of "test" subfolder within file repositoty. It should look like on picture below:
This gives us an indication, that there is either a transfer in progress, or the transfer was not completed.
So in order to get rid of incompleted files, all is needed, is to search for the older files containing "__IN_TRANSFER__" in their names, and delete them.