Thursday, January 18, 2024

DIY - customizing my walk in closet


This is all about how I turned my walk-in closet into a great-looking space





During my annual leave in the end of the year, My wife motivated me to customize our main walk-in closet. So we could customize it from the basic to fully modernized look with smart moving sensor lights. 



 


It was not easy and it required a lot of patience to get done :) I should thank Stefani who had a nice video in YouTube about DIY walk-in-closet makeover where you can find the YouTube recording in [1] 

I used her hack of IKEA drawers which it saved me a lot of time and effort in making my own drawers. 

Cleaning up the existing closet:

As you see in the above picture, it came up with a shelf around the closet attached to the drywall. We have to carefully remove that without damaging the drywall. It might be got attached to the drywall even if you remove the screws as finishing nails may be there. When you are trying to remove, you can insert some flat metal thing, in the back of the attached board and give a little lift slowly. "PLEASE NOT USE SCREWDRIVER" for this task, as it is not big enough and can damage the drywall. 

In my case, I used a  metal BBQ spatula to get the thing done. You might use any other tool you have :)


Please get the help of some other person with you as these boards are heavy and existing nails can cause accidents. 

I decided not to remove the existing carpet as this closet is in my upper floor. So, after removing the shelf it looks like follows.



Then I first installed a base on the floor. I used 4x2s from Home Depot. If you are planning to have this kind of project, I highly recommend planning well ahead and buying the wood sometime before you start working. Most of the time the 4x2s you find in HD are wet, It is better to give them some time to get them dried. 




I bought 4x8, 3/4 inch plywood from HD [2] and used the circular saw to cut them out as per the measurement. Please wear safety glasses and ear protection when you are using the circular saw. 

Then I installed the IKEA Dresser and the verticals. In my case, i used 6 drawers TARVA dresser as per the space I have in my closet. 




Then I installed the shelves to get a good appearance.



As the last step of installation, I installed the top part of connecting to the top of the ceiling.


The next step was to paint, However before you start painting, it is essential to do the sanding. I used Sander for that and after using 280 pieces of sandpaper, I finished it with 400. You have to wear a good mask, eye protection, and ear protection on this and it will take a lot of time :)

Then, I used painter's tape to cover the edges and a cover for the carpet before started painting. Here you can find my two little boys helping me out :)




Initially, I used paint brushes and rollers and it took me a lot of time to finish and gave me a lot of body ache. Then I found the sprayer from the Harbor Freight without spending much. I recommend you to get it to save a lot of time and effort. It is less that $80 in 2023.



I used 2 coats of Primer paint and then the white color glossy paint for finishing. Then you can buy chrome heavy-duty closet poles and brackets from HomeDepot and install them which gives a great look.



Finally, the lighting part was done using the LED light strips and the motion sensors from Amazon. 


I was really satisfied with the outcome of the entire project and it took me about ~3 weeks to complete as we had the Christmas break in the middle. I could complete the entire customization for under ~$1500 and it is really worth it. 


Happy woodworking!!


[1] https://www.youtube.com/watch?v=--L2xAIV0Kg

[2] https://www.homedepot.com/p/SANDEPLY-18mm-Sande-Plywood-3-4-in-Category-x-4-ft-x-8-ft-Actual-0-709-in-x-48-in-x-96-in-454559/203414066



Thursday, August 5, 2021

Retrospect : Intermittent web service calls to WSO2 fails

 Modern day business is highly reliable on web services. As almost every thing is connected, If something in the middle connection breaks, It is a business loss. So, With my experience in Customer Success team, I thought to share one my experiences where we encountered with WSO2 enterprise service bus or Enterprise integrator. 


The problem we got was, the client who was invoking the service of WSO2 ESB was getting a timeout when making the connection to WSO2 server. This was not happening for all the calls, But intermittently. When we analyzed the logs, we could not locate any issue inside the server.  

Then we checked the thread dumps for finding out any clue where it can have that kind of behavior. But we were clueless. 

Then as the next step, We mapped the timings of client requests and the log timings and we could see that given specific requests which was failing is not reaching inside WSO2 server. 

Damn... What do we do now? 

Then we captured the TCP dump for suspicious things. During that time period, We observed following pattern of packets.



If you are familiar with the flow for making the TLS connection, it is as follows.

image courtesy: https://hpbn.co/transport-layer-security-tls/



So, When making a TLS connection from the client side to the server side, Client Sends a "SYN" packet, and server needs to respond to it with a "SYN, ACK" packet. 

But in the previous image, you can see that, even-though client sent the "SYN" packet, It did not get the response "SYN,ACK" packet from the server. Then client does three more TCP RETRANSMISSIONS. But server is not responding. 

Then after some time, With a different port, Client sends "SYN" and server sends "SYN,ACK" as expected.

So, this we narrowed down to know the cause on why WSO2 ESB did not respond, It was because Client could not make the connection to the WSO2 server. Then we researched on what could cause this kind of behavior and we ended up with multiple posts like [1] [2]

Upon those, We could narrow down following entry which we asked to add in the /etc/sysctl.conf  file [3] seems to be the key factor for this behavior.

net.ipv4.tcp_tw_recycle

Basically, When there is NAT ( Network Address Translation) happening in the communication path, Having above property configured with value "1" could cause this kind of intermitted TCP communication behaviors. 

In WSO2 document you have following warning.

Note

Change this with caution and ONLY in internal networks where the network connectivity speeds are faster.
It is not recommended to use net.ipv4.tcp_tw_recycle = 1 when working with network address translation (NAT), such as if you are deploying products in EC2 or any other environment configured with NAT. 

So, Ultimately we could resolve the problem by removing this entry. So, I believe it would be worth to know this in your cases where you encounter the same.

Enjoy!!

[1] https://serverfault.com/questions/235965/why-would-a-server-not-send-a-syn-ack-packet-in-response-to-a-syn-packet

[2] https://www.programmersought.com/article/45056975684/

[3] https://docs.wso2.com/display/EI600/Network+and+OS+Level+Performance+Tuning


Wednesday, August 5, 2020

Download / Get Public certificate of secured websites / HTTPs endpoints


In our day today life, Sometimes we need to get the public certificate of various HTTPs endpoints to invoke them securely.

So, if you are a MAC OS user, you ll have a hard time since google chrome is not having the option to download it as 2020 and Firefox also not giving it as a single one. You have to go through certificate chain to get it.

However, If you have a single command to get it, It is very convenient. With Open SSL, We can get it easily.

Following is the pattern.

$ echo | openssl s_client -servername NAME -connect HOST:PORT |\
  sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > certificate.crt

Short explanation:
OptionDescription
-connect HOST:PORTThe host and port to connect to
-servername NAMEThe TLS SNI (Server Name Indication) extension (website)
certificate.crtSave SSL certificate to this file


Example:

$ echo | openssl s_client -servername run.mocky.io -connect run.mocky.io:443 |\
  sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > certificate.crt

I found this information from [1] and here is my gratitude to the author of that side.

Enjoy!!!

[1] https://www.shellhacks.com/get-ssl-certificate-from-server-site-url-export-download/

Response time for curl commands

In our day today life when we are using CURL commands, It is worth that if we can measure the time it took to respond. In curl , we can write out the time taken for many of the cases.

You can read information about them from the man page of the CURL too.

For the simplicity i would post following here.

curl -w'%{time_total}' -X  GET "https://run.mocky.io/v3/7f8d8e53-b0a3-47bd-b2e6-fda5f449b0be"


you ll get a response like follows.

{"shammi":"jayasinghe"}1.496453 

you can see, it has taken about 1.49 seconds for overall response.


You can read about -w operation and about the flags from man curl page or from [1] which i learnt to use these

[1]  https://ops.tips/gists/measuring-http-response-times-curl/

Thursday, January 2, 2020

Unique index or primary key violation: "PRIMARY KEY ON """".PAGE_INDEX"; SQL statement:


When we try to connect to the embedded H2 database from H2 clients such as DBEver, I was getting following error message

Unique index or primary key violation: "PRIMARY KEY ON """".PAGE_INDEX"; SQL statement:
ALTER TABLE PUBLIC.IDN_OAUTH2_ACCESS_TOKEN_SCOPE ADD CONSTRAINT PUBLIC.CONSTRAINT_B1 FOREIGN KEY(TOKEN_ID) REFERENCES PUBLIC.IDN_OAUTH2_ACCESS_TOKEN(TOKEN_ID) ON DELETE CASCADE NOCHECK [23505-200]

When i search for this issue, It seems to be introduced with bug fixes for H2 database. Since in WSO2 we use H2 as the default database, we encountered this issue when connecting the H2 database.

So, we can avoid this issue by adding following part to the end of the database URL.


;mv_store=false

Once we added it , the full URL will look like follows.


jdbc:h2:/Users/shammijayasinghe/wso2am-2.6.0/repository/database/WSO2AM_DB;mv_store=false


Hope this helps.. Enjoy!!!

[1] https://groups.google.com/forum/#!topic/h2-database/5LZlZ_jC4QI

Tuesday, October 10, 2017

WSO2 API Manager with Consul for Dynamic endpoints in distributed deployment


WSO2 API Manager 2.1.0 + is fully capable of supporting dynamic endpoints. As you see in the documentation [1], In order to use the dynamic endpoint, You need to us TO header

The dynamic endpoint sends the message to the address specified in the To header. You can configure dynamic endpoints by setting mediation extensions with a set of conditions to dynamically change the To header. 

As you may already understand, with the above implementation, We are setting the to header in the mediation extension as a hardcoded value. If you want to change the endpoint, you need to set the correct mediation extension and re-publish the API.


QUESTION:

How can we change the endpoint dynamically, without re-publishing the API?

- You can read the endpoint from a database
- You can read the endpoint from the file system
- You can use a service registry like Consul

When it comes to production deployment, Calling a DB for each every API request is pretty expensive. What can we do?

Can't we cache the DB response?

Yes, We can. But when the cache is expiring. What if I want to change the endpoint before cache expires?

Same thing with the file system also. Reading from the file for each and every API call is pretty expensive.

Apart from the above, When it comes to distributed deployment in a production environment which multi-data centers,  We can not use a database or filesystem until they are shared.

We can overcome all of the above issues with using a multi data center supported service discovery tool which is Consul.

How to use consul with WSO2 API Manager

  • Downloaded consul binary from https://www.consul.io/downloads.html
  • Added the consul to the $PATH
    export CONSUL_HOME=/Users/shammijayasinghe/wso2/tools/consul;
    export PATH=$PATH:$CONSUL_HOME
    
  • Created a directory for data of consul /Users/shammijayasinghe/wso2/tools/consul/data
  • Started the consul with the command consul agent -server -bind=0.0.0.0 -data-dir=/Users/shammijayasinghe/wso2/tools/consul/data1 -bootstrap

Shammis-MacBook-Pro:consul shammijayasinghe$ consul agent -server -bind=0.0.0.0 -data-dir=/Users/shammijayasinghe/wso2/tools/consul/data1 -bootstrap
==> WARNING: Bootstrap mode enabled! Do not enable unless necessary
==> Starting Consul agent...
==> Consul agent running!
           Version: 'v0.9.2'
           Node ID: 'a51633be-0115-ccd2-dd25-4d70cf5d6afa'
         Node name: 'Shammis-MacBook-Pro.local'
        Datacenter: 'dc1'
            Server: true (bootstrap: true)
       Client Addr: 127.0.0.1 (HTTP: 8500, HTTPS: -1, DNS: 8600)
      Cluster Addr: 10.0.0.3 (LAN: 8301, WAN: 8302)
    Gossip encrypt: false, RPC-TLS: false, TLS-Incoming: false

==> Log data will now stream in as it occurs:

    2017/09/01 08:32:46 [INFO] raft: Initial configuration (index=1): [{Suffrage:Voter ID:10.0.0.3:8300 Address:10.0.0.3:8300}]
    2017/09/01 08:32:46 [INFO] raft: Node at 10.0.0.3:8300 [Follower] entering Follower state (Leader: "")
    2017/09/01 08:32:46 [INFO] serf: EventMemberJoin: Shammis-MacBook-Pro.local.dc1 10.0.0.3
    2017/09/01 08:32:46 [WARN] serf: Failed to re-join any previously known node
    2017/09/01 08:32:46 [INFO] serf: EventMemberJoin: Shammis-MacBook-Pro.local 10.0.0.3
    2017/09/01 08:32:46 [WARN] serf: Failed to re-join any previously known node
    2017/09/01 08:32:46 [INFO] consul: Handled member-join event for server "Shammis-MacBook-Pro.local.dc1" in area "wan"
    2017/09/01 08:32:46 [INFO] consul: Adding LAN server Shammis-MacBook-Pro.local (Addr: tcp/10.0.0.3:8300) (DC: dc1)
    2017/09/01 08:32:46 [INFO] agent: Started DNS server 127.0.0.1:8600 (udp)
    2017/09/01 08:32:46 [INFO] agent: Started DNS server 127.0.0.1:8600 (tcp)
    2017/09/01 08:32:46 [INFO] agent: Started HTTP server on 127.0.0.1:8500
    2017/09/01 08:32:52 [WARN] raft: Heartbeat timeout from "" reached, starting election
    2017/09/01 08:32:52 [INFO] raft: Node at 10.0.0.3:8300 [Candidate] entering Candidate state in term 8
    2017/09/01 08:32:52 [INFO] raft: Election won. Tally: 1
    2017/09/01 08:32:52 [INFO] raft: Node at 10.0.0.3:8300 [Leader] entering Leader state
    2017/09/01 08:32:52 [INFO] consul: cluster leadership acquired
    2017/09/01 08:32:52 [INFO] consul: New leader elected: Shammis-MacBook-Pro.local
    2017/09/01 08:32:52 [INFO] agent: Synced node info


Now the consul server is up and running on my local machine. Now what we need to do is we need to add a key-value pair to the consul registry.

Insert a Key-Value pair using API call

curl     --request PUT     --data "http://www.mocky.io/v2/59a96c49100000300d3e0afa"     http://127.0.0.1:8500/v1/kv/MyMockEndpoint

check and verify whether the key-value pair is available in consul

curl     http://127.0.0.1:8500/v1/kv/MyMockEndpoint


[{"LockIndex":0,"Key":"MyMockEndpoint","Flags":0,"Value":"aHR0cDovL3d3dy5tb2NreS5pby92Mi81OWE5NmM0OTEwMDAwMDMwMGQzZTBhZmE=","CreateIndex":8,"ModifyIndex":183}]

Now it is verified that with the API call, We can retrieve the value we stored.

Next step is to use this within wso2 API Manager. In order to do that, I have created a mediation extension with the following synapse configuration.



 <?xml version="1.0" encoding="UTF-8"?>  
 <sequence name="customRoutingSequence" trace="disable" xmlns="http://ws.apache.org/ns/synapse">  
   <log>  
     <property name="State" value="Inside Custom Routing Sequence"/>  
   </log>  
   <call blocking="true">  
     <endpoint>  
       <address uri="http://127.0.0.1:8500/v1/kv/MyMockEndpoint"/>  
     </endpoint>  
   </call>  
   <log level="full">  
     <property name="Response From Consul" value="======"/>  
   </log>  
   <property description="consulEndpoint" expression="json-eval($.[0].Value)" name="consulEndpoint" scope="default" type="STRING"/>  
   <property description="decodedConsulEndpoint" expression="base64Decode($ctx:consulEndpoint)" name="decodedConsulEndpoint" scope="default" type="STRING"/>  
   <log>  
     <property expression="$ctx:decodedConsulEndpoint" name="decodedConsulEndpoint"/>  
   </log>  
   <header name="To" expression="$ctx:decodedConsulEndpoint"/>  
 </sequence>  




As you can notice, In above mediation extension, I am using a blocking call to the consul endpoint and retrieve the endpoint. But as it is encoded with base 64, In order to use it, I have to decode it.

I am decoding it with the following property mediator.


 <property description="decodedConsulEndpoint" expression="base64Decode($ctx:consulEndpoint)" name="decodedConsulEndpoint" scope="default" type="STRING"/>  


Then I am setting it to the TO header as we discussed in the beginning.
 
  <header name="To" expression="$ctx:decodedConsulEndpoint"/>  

Then we have to create an API with using
- Above created mediation extension
- Using the endpoint type as Dynamic


Once deployed, Invoke the API.

Then in order to check the dynamic endpoint change, Change the value of the above key by following curl command.


 curl   --request PUT   --data "[newEndpointURL]"   http://127.0.0.1:8500/v1/kv/MyMockEndpoint  

Once you provide the new endpoint URL above, You should be able to see that API is invoking this given backend URL without republishing the API.

With this way, We can make the API Manager really flexible in a distributed environment, As consul can be configured as a cluster and supported with Multi Data Centers. So, You can get your requiement of changing the backend endpoint of a cluster of API Manager which contains any number of nodes with a single curl command.


[1] https://docs.wso2.com/display/AM210/Working+with+Endpoints

Monday, August 28, 2017

Deploy WSO2 products with valid CA (Certificate Authority) signed certificate

This blog post will contain multiple posts as it is too long to have all the information in one post.

Part 1 - Creating a keystore and generating Certificate Signing Request (CSR)


When you are searching for the topic of this post or for the following exception on the internet with related to WSO2, you will come across following article from Amila Jayasekara [1]


 curl: (60) Peer certificate cannot be authenticated with known CA certificates  
 More details here: http://curl.haxx.se/docs/sslcerts.html  
 curl performs SSL certificate verification by default, using a "bundle"  
 of Certificate Authority (CA) public keys (CA certs). If the default  
 bundle file isn't adequate, you can specify an alternate file  
 using the --cacert option.  
 If this HTTPS server uses a certificate signed by a CA represented in  
 the bundle, the certificate verification probably failed due to a  
 problem with the certificate (it might be expired, or the name might  
 not match the domain name in the URL).  
 If you'd like to turn off curl's verification of the certificate, use  
 the -k (or --insecure) option.  


It is a great article from Amila and i followed the same some time back. However, I thought to share my experience on using easy UI tool for the same task.

When it comes to using CA (Certificate Authority) signed certificate in your production server, There are few steps to carry out.

First, you need to decide whether you are going to use your already existing and valid CA signed certificate or whether you are going to create new keystore and generate key pair and get them signed from a CA.

So here we are discussing both of those approaches.

1. Create a keystore and generate keypair and use them for configuring
2. Use existing keypair in default wso2 keystore

The tool which i am going to use here is Keystore Explorer. You can get it from [2]

Creating a keystore and keypair

Launch Keystore Explorer



Select Create a new key store


Choose KeyStore type as JKS and then save (CTRL + S). It will ask for password for keystore.

Note: When using WSO2 products, Key password and Keystore password should be same.


After setting the password, It will ask for the name for the keystore. You can provide any name and save it.


Once you saved it, Generate a key pair from the tools menu as bellow.

It will ask for the algorithm

It will ask for the other fields

You need to provide the host name as your CN when you configuring the name field by clicking on the icon in front of the name field as bellow.

then you have to confirm the information.


Now it will ask for the key alias, By default it will select the given CN name.


Provide a password for the key pair. As in the above given note When using WSO2 products, Key password and Keystore password should be same

Now we done with the process of generating the keypair.

Our next step is to create a Certificate Signing Request (CSR) from the above keypair

Creating a CSR (Certificate Signing Request)

By right clicking on the keypair , you can select the Generate CSR option. It will generate the CSR and ask for saving.



In my case it will generate it as myhostname.net.csr. When you open it with text editor, It will look like follows. This is the one you need to provide to the Certificate Authority (CA) to get it signed.



[1] http://wso2.com/library/knowledge-base/2011/08/adding-ca-certificate-authority-signed-certificate-wso2-products/
[2] http://keystore-explorer.org/