Friday, April 1, 2022

Local Kubernetes step by step

 Hello, 

After reading this article https://www.infoq.com/news/2022/03/lyft-cloud-local-dev/ I became curious of exploring development with local kubernetes. Until now I was proponent of using production grade kubernets like GKE or EKS. The idea being to be the closer possible from production. But it has some drawbacks:

- it is not free

- it is frustrating to spend time with credentials issues

- it takes significant time to create and destroy a cluster each time you want to play with kubernetes


So in this article I will give all the commands to execute in order to create a kubernetes cluster on local machine. 

 

The cluster will be created with KIND (https://kind.sigs.k8s.io/)  but there are other options like minikube or k3d. It is easy to change, it is just a parameter of ctlptl command (for example ctlptl create cluster k3d --registry=ctlptl-registry instead of ctlptl create cluster kind --registry=ctlptl-registry). To explain better, KIND is not used directly but through ctlptl which make it easier.


At first, I highly suggest to do it in a fresh installed VM. I did it with an Ubuntu 18.04.6 running on VirtualBox (can be downloaded here https://www.osboxes.org/ubuntu/)


Note:

During installation you may encounter an error about locking on dpkg frontend (it is an issue with the osboxes vm). To fix:

 

sudo rm /var/lib/apt/lists/lock
sudo rm /var/cache/apt/archives/lock
sudo rm /var/lib/dpkg/lock*
sudo dpkg --configure -a

Details here:  https://askubuntu.com/questions/1109982/e-could-not-get-lock-var-lib-dpkg-lock-frontend-open-11-resource-temporari


1) Docker installation


sudo apt-get update

 
sudo apt-get install \
   ca-certificates \
   curl \
   gnupg \
   lsb-release
 
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
 
sudo apt-get update
 
sudo apt-get install docker-ce docker-ce-cli containerd.io


Details here: https://docs.docker.com/engine/install/ubuntu/

Check it is working: sudo docker run hello-world

 

2) Setup docker as a non-root user (optional)

 

sudo usermod -aG docker $USER

 

Restart the VM

Check it is working: docker run hello-world

Details here: https://docs.docker.com/engine/install/linux-postinstall/

3) Install kubectl 


curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"

sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl


Details here: https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/


4) Install brew

Brew will be used to install kind and ctlptl


/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"


Remark: after the installation of brew there are a few commands to run (3 at the time of writing). just follow what is displayed in the console. 


Details here: https://brew.sh


5) Install kind

In order for ctlptl to create a cluster through KIND it is necessary to install the kind executable


brew install tilt-dev/tap/ctlptl

Details here: https://github.com/tilt-dev/ctlptl

 

6) Create the cluster

 

And now that all the preparation steps are done we can create the cluster and its registry.

 

ctlptl create registry ctlptl-registry --port=5005

ctlptl create cluster kind --registry=ctlptl-registry


It will take some time. After it is finished verify it is working:


kubectl get pods


And that's it. Now a kubernetes cluster is created and you can play with it ;-)


Next Steps


Why not create a pod and log to it?

kubectl run my-shell --rm -i --tty --image ubuntu -- bash


Or create an ingress with Kong gateway?

https://docs.konghq.com/gateway/2.8.x/install-and-run/kubernetes/


Or try Tilt (which was the reason I wanted a local cluster)

Install tilt: https://docs.tilt.dev/tutorial/1-prerequisites.html

Start up sample application: https://docs.tilt.dev/tutorial/2-tilt-up.html

 

My notes on github:

https://github.com/sellerin/notes/blob/main/TILT_LOCAL_KUBERNETES.md


Thank you for reading.


Sunday, July 12, 2020

Envoy Control Plane Hello World

Hi,

In this post I would like to explain how to configure Envoy proxy to work with a control plane. I spent some time reading documentation about Envoy and I didn't find nothing for having something up and running for beginners like me. I hope to fill this gap.

To describe Envoy very quickly it is a proxy like Nginx or HAProxy but with the difference that its configuration can be dynamic and piloted through API. I was very curious to set up an example where I can modify the upstream IP address by API.

For more information please refers to Envoy documentation (https://www.envoyproxy.io/docs/envoy/latest/) or this blog article https://blog.envoyproxy.io/service-mesh-data-plane-vs-control-plane-2774e720f7fc which give a bigger picture of control plane and service mesh.

So let's go back to this tutorial. What we will achieve is:



We will use java-control-plane only for EDS functionality. All the rest will be configured statically by a yaml file. What it is interesting is that Envoy can be used in a lot of configuration from fully dynamic by using EDS, CDS, LDS, etc or fully static. We'll take an hybrid approach. Once you understand how it works for EDS it is easy to adapt for the others.

Important concepts with Envoy are listeners (LDS), clusters (CDS) and endpoints (EDS). In our example the listener is configured to be on port 10000. A cluster is a list of endpoints that provide a service (in our example the cluster name is some_service). Endpoints are pairs of IP address/port number associated to a cluster.

Envoy will connect to a control plane to retrieve endpoint configuration (in our example the endpoint 127.0.0.1:8000 is given by the control plane).

First of all you need the Envoy binary. What I did is build it locally by following https://github.com/envoyproxy/envoy/tree/master/ci#building-and-running-tests-as-a-developer. If you go this way I suggest to do it with a release version and not master branch where some unit tests may fail (I did it with v1.14.3 without issue). Another option is to use the docker image.

You will also need the java-control-plane: https://github.com/envoyproxy/java-control-plane (it is easier to use than go-control-plane):

git clone https://github.com/envoyproxy/java-control-plane 

Pre-requisite: 

1) Modify java-control-plane to use it as an EDS

The modification consists in adding an endpoint to some_service cluster in the snapshot. some_service cluster is commented as it is defined by static resource (see content of bootstrap-xds.yaml bellow). Just to help understand, each time you want to change the topology of your mesh you create a new snapshot. The default version of TestMain.java contains two snapshot creation but for this tutorial only the first one is necessary so the second one is commented.

Modify TestMain.java as follow:

 2) Add bootstrap-xds.yaml  to Envoy directory:


Takeaways from this configuration:
- Envoy is listening on port 10000
- Requests to 10000 are sent to the cluster some_service
- The endpoints of cluster some_service are provided by EDS
- EDS server is running on port 12345

Now that all configuration is done, let's start the services

1) Start the upstream

Start an http server listening on port 8000 with python

python3 -m http.server 

2) Start Envoy with bootstrap-xds.yaml configuration

./envoy -c bootstrap-xds.yaml --drain-time-s 1 -l debug 
NB: you can access Envoy stats at http://127.0.0.1:19000



3) Start the control plane

Run TestMain.java from java-control-plane project

4) Verify it works

Make a request to http://127.0.0.1:10000/ and it should be redirected to http://127.0.0.1:8000/

I hope this tutorial can help getting started with Envoy with a very practical example that you can build on.

Sunday, October 15, 2017

Sign SAML 2 AuthnRequest

Hi,

In order to continue on studying SAML requests. Let's complete the code of the last post to add a signature to the AuthnRequest. To run the following code the only requisite is to generate a key pair using Java KeyTool : https://docs.oracle.com/javase/8/docs/technotes/tools/unix/keytool.html

Here there is the code :


It will generate the following request :


To be sure the request is valid, you can verify with https://www.samltool.com/validate_authn_req.php

Sunday, October 1, 2017

Generate SAML 2 AuthnRequest by using OpenSAML 3

Hi,

I will start series of posts on SAML 2 about how to generate messages, parsing them and validating them.

First of all, to dig into the subject I really recommend to read the saml technical overview. It has everything needed to understand SAML and it is well written.

In this post I will show how to generate an AuthN request using Java and we will validate the request by using an online tool : https://www.samltool.com/online_tools.php.

You can check how AuthN requests are used in SAML protocol in the following diagram :

This diagram shows the use case "SP-Initiated SSO". Refer to the technical overview mentioned above to have all details.

To generate the AuthnRequest we will use OpenSAML 3. As the website is stating there isn't a lot of documentation on this version of OpenSAML so I took some time to adapt existing code to get the snippet bellow. The original code can be found on this blog :  http://www.john-james-andersen.com/blog/programming/sample-saml-2-0-authnrequest-in-java.html (thanks to the author of this blog)


To make it run, add the following dependencies in your Maven project

<dependency>
    <groupId>org.opensaml</groupId>
    <artifactId>opensaml-core</artifactId>
    <version>3.3.0</version>
</dependency>
<dependency>
    <groupId>org.opensaml</groupId>
    <artifactId>opensaml-saml-api</artifactId>
    <version>3.3.0</version>
</dependency>
<dependency>
    <groupId>org.opensaml</groupId>
    <artifactId>opensaml-saml-impl</artifactId>
    <version>3.3.0</version>
</dependency>
<dependency>
    <groupId>net.shibboleth.utilities</groupId>
    <artifactId>java-support</artifactId>
    <version>7.3.0</version>
</dependency>

The last dependency (net.shibboleth.utilities) is for the pretty print of the SAML message.

By running the code, here there is the SAML AuthnRequest that is generated :

<?xml version="1.0" encoding="UTF-8"?>
<saml2p:AuthnRequest
    AssertionConsumerServiceURL="http://sp.example.com/demo1/index.php?acs"
    Destination="http://idp.example.com/SSOService.php"
    ForceAuthn="true" ID="ONELOGIN_6f319749-6db0-4ac6-be72-cb223d5870a4"
    IsPassive="false" IssueInstant="2017-10-01T18:20:31.096Z"
    ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
    Version="2.0" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
    <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://sp.example.com/demo1/metadata.php</saml2:Issuer>
    <saml2p:NameIDPolicy AllowCreate="true"
        Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient" SPNameQualifier="SERVICE_PROVIDER_ID"/>
    <saml2p:RequestedAuthnContext Comparison="minimum">
        <saml2:AuthnContextClassRef xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef>
    </saml2p:RequestedAuthnContext>
</saml2p:AuthnRequest>

The last thing to do is to validate this message, we will use this nice online tool : https://www.samltool.com/validate_authn_req.php. Another way to validate the message would by using OpenSAML itself. It may be the subject of another post on this blog.


I hope this article will help you getting started with SAML message generation. To continue on the subject I will try to add digital signature to this generated message in order to improve security but it will be in another post.

Thank you for reading!

Monday, May 1, 2017

The Name Constraints Extension

A very interesting article about Name Constraints Extension on certificates : https://medium.com/netflix-techblog/bettertls-c9915cd255c0 . @Netflix , Thanks !

Tuesday, December 27, 2016

Secure an API with OAuth2

When it comes to secure a webservice there are several options. One of them is OAuth2 and I will
explain how to have an hello world example running by using Sprint Security OAuth.


Some theory 

To my understanding OAuth2 is all about giving to a third-party a limited access to a ressource. Hum, pretty abstract ... With an example it will be clearer:

Let's say you are reading and article in your favorite dev news website. For example this one : Securing MongoDB Instances

You can notice a Tweet button (*) on top of the article. By clicking it, you will post a tweet in your twitter account with a link to the article you are reading. What it is really going on is that DZone website will be granted an access to your twitter account for a limited time and with limited functionality just to be able to tweet on your behalf. This grant will be given by you by entering your credentials on twitter (**), it is done by redirection and by this action you will allow DZone to access your twitter account. Notice that you never shared your credentials with DZone, you only connected to Twitter.

If it's still not clear, there is an analogy that helped me to understand (it's not from me but I don't remember where I have read it). Imagine you are the owner of a car (the ressource) and you want to go to a fancy restaurant  where someone (third-party) will drive your car (access to a ressource you own) to the restaurant's parking. You don't know this person and give him the key of your car is a risk because he can go away with it. For such situation, car manufacturers came up with a solution which is to provided a special key for the car that only work for a limited distance, it means that you can drive the car only a few meters with this key. So to limit the risk to be stolen from your car, you can give this special key (token) to the restaurant employee.

And if it's still not clear, everything can be found here : The OAuth 2.0 Authorization Framework


Hello world up and running 

For the hello world, what we want to do is to protect the access to a rest API that returns Hello World. We want this API to be callable only by users owning a token provided by an OAuth2 authorization server. Withing OAuth2 framework this use case is called : Bearer Token Usage.

I really encourage to read the documentation about bearer token which is a kind of easier form to use OAuth2 (no redirection), it's perfect for starting. And for hurried readers, have at least a look at the sequence diagram (***).

Well, that's time to make things work. For this, the spring-security-oauth project is bundled with integration tests and we will use the one called Vanilla which is exactly what we want to do.

Quote from the documentation about Vanilla:
"This project shows what you can do with the minimum configuration to set up an Authorization Server and Resource Server"

All you need to do is to clone the project in your machine (git clone https://github.com/spring-projects/spring-security-oauth) and then in the Vanille folder run the command :

mvn spring-boot:run

It will start a tomcat server listening on 8080.

As a client, here are the requests to make if you want to access the protected API
$ curl -H "Accept: application/json" my-client-with-secret:secret@localhost:8080/oauth/token -d grant_type=client_credentials
{... "access_token": "b561ff06-4259-466e-92d8-781db1a51901", ...}
$ TOKEN=b561ff06-4259-466e-92d8-781db1a5190
$ curl -H "Authorization: Bearer $TOKEN" localhost:8080/
Hello World
You basically make a first call by providing a login and password to get a token. Then you can request the API with the token.

One very important thing to keep it mind is that TLS is mandatory with OAuth2. Credentials my-client-with-secret/secret have to be kept secret.

To verify that everything works, try to make a call with an incorrect password and also make a call with an incorrect token. Those calls will be rejected.

For the understanding of this simple scenario be complete, please have a look at Application.java in Vanilla project. The API is protected just by adding @EnableResourceServer annotation. And I let you see how the authorization server is implemented with spring.

Conclusion

OAuth2 is one way to protect an API. By having a simple hello world application running I believe it is easier to understand OAuth2  and by iterating achieve more complex use cases.

I'm planning to make this exact same scenario work with Node.js. With spring it was really straightforward. I hope it will be the same with Node.js but from my first researches I think it will need more work.

Thank you for reading!

(*)


(**)


(***)

Saturday, December 24, 2016

JVM Key size limitation

The Oracle JDK limits the key size it is possible to use for cryptography. Here there is an utility class that can check if your JVM has this limit.


KeyLengthDetector.java (thanks to jehrhardt)

1) Let's run it in a limited JVM :







We can see the key length is limited to 128.

If you can to suppress this limitation , it is possible by installing JCE on the JRE.

2) And now we run it on OpenJDK 9:








key length is : 2147483647