banner



How To Check Web Service Is Up And Running

Published in December 2020


Authentication between microservices using Kubernetes identities


If your infrastructure consists of several applications interacting with each other, you lot might have faced the issue of securing communications betwixt services to forbid unauthenticated requests.

Imagine having two apps:

  1. An API
  2. A information shop

You lot might want the data store merely to respond to requests to the API and reject requests from anywhere else.

How would the data store make up one's mind to allow or deny the request?

A popular approach is to asking and pass identity tokens to every call within services.

So instead of issuing a request to the information store directly, you might demand to go through an Authentication service first, think a token and employ that to authenticate your asking to the data store.

There is a specific context associated with the token that allows the data store to accept a token from the API service and to reject it from elsewhere.

This context is used to permit or deny the request.

You have several options when it comes to implementing this authentication machinery:

  • You could use static tokens that don't expire. In this case, in that location is no demand for running a dedicated authentication server.
  • You could gear up an OAuth server.
  • You could curl out your authentication and authorisation mechanism such equally common TLS certificates.

All the hallmark and authorisation servers have to do is to:

  1. Authenticate the caller - The caller should accept a valid and verifiable identity.
  2. Generate a token with a limited scope, validity and the desired audience.
  3. Validate a token - Service to service advice is allowed only if the token is legit for the ii services involved.

Examples of defended software that allows you to implement hallmark and authorisation infrastructure are tools such equally Keycloak or Dex.

When yous use Keycloack, you first:

  1. Login using your email and countersign — your identity is verified.
  2. A valid session is created for your user. The session might describe what groups you belong to.
  3. Every request is validated and you will be asked to log in once more when it's invalid.

The same applies to 2 apps inside your infrastructure.

  1. A backend component makes a request to Keycloack with its API primal and secret to generate a session token.
  2. The backend makes a request to the second app using the session token.
  3. The second app retrieves the token from the asking and validates information technology with Keycloak.
  4. If the token is valid, it replies to the request.

You lot might non accept noticed, but Kubernetes offers the aforementioned primitives for implementing authentication and authority with Service Accounts, Roles and RoleBindings.

In Kubernetes, you assign identities using Service Accounts.

Users and Pods tin can utilise those identities as a machinery to authenticate to the API and effect requests.

Service Accounts are and then linked to Roles that grant admission to resources.

If a Role grants access to create and delete Pods, y'all won't be able to ameliorate Secrets, or create ConfigMaps — for example.

Could you utilise Service Accounts as a machinery to authenticate requests between apps in the cluster?

What if the Kubernetes API could be used as an Authentication and Authorisation server?

Let'southward try that.

Creating the cluster

You will need access to a Kubernetes cluster with the Service Account Volume projection feature enabled.

Don't worry if you lot don't know what a Service Account Volume is — you will learn more about it subsequently on in the article.

The Service Account Volume projection feature requires the Kubernetes API server to be running with specific API flags.

The support for different managed Kubernetes providers may vary.

However, yous tin beginning a local cluster with the volume projection characteristic enabled in minikube with:

bash

                          minikube get-go                \                --extra-config=apiserver.service-business relationship-signing-key-file=/var/lib/minikube/certs/sa.central                \                --extra-config=apiserver.service-business relationship-central-file=/var/lib/minikube/certs/sa.pub                \                --extra-config=apiserver.service-account-issuer=kubernetes/serviceaccount                \                --extra-config=apiserver.service-account-api-audiences=api                      

You should also clone this repository as information technology contains the demo source code that will be referred to in the article.

You will now deploy 2 services:

  1. You will refer to these services as the API service and the Data store.
  2. They are written in the Go programming language, and they communicate via HTTP.
  3. Each service runs in its namespaces and use defended Service Accounts identities.
  4. The information store replies to requests successfully but when the caller has a valid identity, else it rejects the request with an fault.

Deploying the API component

The API service is a headless web awarding listening on port 8080.

When you brand a request to it, the API component:

  1. Issues an HTTP GET request to the Data store with its Service Account identity.
  2. Forrard the response.

You lot tin deploy the app and betrayal information technology as a Service in the cluster with:

bash

                          kubectl apply -f service_accounts/api/deployment.yaml                            namespace/api created serviceaccount/api created deployment.apps/app created service/app created                                    

Yous can retrieve the URL of the API service with:

fustigate

                          minikube --namespace api                service                app --url                            http://192.168.99.101:31541                                    

If you lot consequence a asking to that app, volition you get a successful response?

Let's try that:

bash

                                          curl                http://192.168.99.101:31541                            Get                "http://app.information-shop.svc.cluster.local"                :                dial tcp: lookup app.data-store.svc.cluster.local: no such                host                                                  

The error is expected since y'all haven't deployed the data store yet.

Go on the last open.

Open a new terminal to carry out the next ready of steps.

Deploying the Data store

The Data shop service is another headless web application listening on port 8081.

When a client makes any request to it, the Information store:

  1. Looks for a token in the request header. If there isn't one, information technology replies with an HTTP 401 fault response.
  2. Checks the token with the Kubernetes API for its validity. If it's invalid, it replies with an HTTP 403 response.
  3. Finally, when the token is valid, it replies to the original request.

Y'all can create the data store with:

fustigate

                          kubectl apply -f service_accounts/information-store/deployment.yaml                            namespace/data-store created serviceaccount/data-store created clusterrolebinding.rbac.authorization.k8s.io/role-tokenreview-binding created deployment.apps/app created service/app created                                    

Now, utilise curl to make a asking to the API service over again:

fustigate

                                          curl                http://192.168.99.101:31541                            Hullo from data store. You have been authenticated                                    

The data store service successfully verified the token and replied to the API.

The API forwards the request to y'all.

What if you make a asking directly to the Information store?

Retrieve the URL of the Data store with:

bash

                          minikube --namespace data-store                service                app --url                            http://192.168.64.28:31690                                    

Let's use curl to make a request to information technology:

fustigate

                                          curl                http://192.168.64.28:31690                            X-Client-Id not supplied                                    

Information technology does not piece of work.

Merely you could supply a dummy X-Client-Id header:

bash

                                          ringlet                -H                'X-Customer-Id: dummy'                http://192.168.64.28:31690                            Invalid token                                    

Excellent!

It does not work!

You protected the data shop from unauthenticated access using Kubernetes and Service Accounts.

You can only brand requests to it if you have a valid token.

But how does all of that piece of work? Let'south discover out.

Under the hood

Service Accounts are a manner to associate your Kubernetes workloads with an identity.

You lot tin can combine a Service Account with a Role and a RoleBinding to define what or who tin can admission what resource in a cluster.

For example, when you lot want to restrict reading Secrets only to admin users in the cluster, yous can do and so using a Service Account.

Service Accounts aren't just for users, though.

You can cosign humans as well as applications in the cluster.

If you lot desire your applications to list all the available Pods in the cluster, you will need to create a Service Account that is associated with read-only access to the Pod API.

When you deployed two apps earlier, y'all also created ii Service Accounts:

fustigate

                          kubectl get serviceaccount --namespace api                            Proper noun      SECRETS   Historic period api                1                4m5s default                ane                4m5s                            kubectl go serviceaccount --namespace data-store                            Proper noun           SECRETS   AGE default                ane                6m4s data-store                ane                6m4s                                    

Those Service Account are the identities associated with the apps, but they don't define what permissions are granted.

For that, yous might need to listing the Role and ClusterRoles:

bash

                          kubectl become rolebindings,clusterrolebindings                \                --all-namespaces                \                -o custom-columns=                'KIND:kind,Function:metadata.name,SERVICE_ACCOUNTS:subjects[?(@.kind=="ServiceAccount")].proper name'                            KIND                 ROLE                       SERVICE_ACCOUNTS RoleBinding          kube-proxy                <none>                ClusterRoleBinding   cluster-admin                <none>                ClusterRoleBinding   kubeadm:get-nodes                <none>                ClusterRoleBinding   role-tokenreview-bounden   information-store                # truncated                                                  

The command above uses kubectl custom columns to filter the output of kubectl go.

The table shows what RoleBinding is linked to a Role (and what ClusterRoleBinding is linked to a ClusterRole).

The only component that has any Role is the Data shop.

There's no Function or Rolebinding for the API.

How come you lot tin take a Service Account without a Role and RoleBinding?

The API app has an empty Service Business relationship that doesn't have any sort of permission.

However, you tin use that Service Account identity to cosign the request to the Kubernetes API (just y'all can't create, update, delete, etc. resources).

What near the Information store?

What kind of access does information technology have?

Let's review the ClusterRoleBinding with:

bash

                          kubectl draw clusterrolebinding role-tokenreview-binding                            Name:         part-tokenreview-binding Labels:                <none>                Annotations:                <none>                Office:   Kind:  ClusterRole                                            Proper name:  system:auth-delegator                            Subjects:   Kind            Name        Namespace   ----            ----        ---------                                            ServiceAccount  data-shop  data-store                                    

From the output above, yous can tell that the ClusterRoleBinding links the data-store Service Account to the system:auth-delegator ClusterRole.

What permissions grants the ClusterRole?

Permit's find out with:

bash

                          kubectl describe clusterrole organisation:auth-delegator                            Proper noun:         system:auth-delegator Labels:       kubernetes.io/bootstrapping=rbac-defaults Annotations:  rbac.authorization.kubernetes.io/autoupdate:                true                PolicyRule:   Resources                                  Non-Resource URLs  Resource Names  Verbs   ---------                                  -----------------  --------------  -----   tokenreviews.hallmark.k8s.io                [                ]                [                ]                [create]                subjectaccessreviews.authorization.k8s.io                [                ]                [                ]                [create]                                                  

The arrangement:auth-delegator ClusterRole has the permissions to telephone call the Token Review API.

What kind of permission is that?

You lot tin use kubectl with the tin can-i subcommand and the impersonation --every bit flag to test permissions:

bash

                          kubectl auth can-i create deployments --as=data-store --namespace data-store                            no                            kubectl auth tin can-i listing pods --equally=information-store --namespace information-shop                            no                            kubectl auth can-i delete services --as=information-shop --namespace data-store                            no                                    

You tin can go along querying all Kubernetes resources, simply the Service Account has merely one permission.

bash

                          kubectl auth tin-i create tokenreviews --every bit=sa-test-one                                            yes                                                  

What'southward a TokenReview?

Issuing requests to the Kubernetes API

The Kubernetes API verifies Service Account identities.

In particular, at that place's a specific component in charge of validating and rejecting them: the Token Review API.

The Token Review API accepts tokens and returns if they are valid or not — yes, it's that elementary.

Allow'southward manually validate the identity for the API component against the Token Review API.

Information technology'due south the Token Review API, and then you might need a token.

What token, though?

Every time y'all create a Service Business relationship, Kubernetes creates a Secret.

The Secret holds the token for the Service Business relationship, and you can utilise that token to call the Kubernetes API.

That's the token that should exist validated confronting the Token Review API.

And so allow's retrieve the token for the API Service Account with:

bash

                          kubectl --namespace api describe serviceaccount api                            Name:                api Mountable secrets:   api-token-lxcb4 Tokens:              api-token-lxcb4                                    

Then to inspect the Underground object, you can issue the following control:

bash

                          kubectl --namespace api describe surreptitious api-token-lxcb4                            Name:         api-token-lxcb4 Type:  kubernetes.io/service-account-token  Data                ==                ==                ca.crt:                1111                bytes namespace:                3                bytes                            token:      eyJhbGciOiJSUzI1NiIsImtpZCI6…                                    

The token object in the Data is a base64 encoded object representing a JSON web token payload.

It's time to verify the token.

To verify the validity of the token, yous demand to create a TokenReview resource:

token.yaml

                                          kind                :                TokenReview                apiVersion                :                authentication.k8s.io/v1                metadata                :                name                :                test                spec                :                                            token                :                eyJhbGciOiJS…                      

You lot can validate the request with:

bash

                          kubectl employ -o yaml -f token.yaml                      

Delight find the flag -o yaml that displays the output of the kubectl apply command.

When you issue the command, the response should look every bit follows:

                                          apiVersion                :                authentication.k8s.io/v1                kind                :                TokenReview                metadata                :                proper name                :                examination                spec                :                token                :                eyJhbGciOiJS…                condition                :                audiences                :                                            -                api                                            authenticated                :                truthful                                            user                :                groups                :                                            -                arrangement:serviceaccounts                -                system:serviceaccounts:api                -                organisation:authenticated                                            uid                :                7df3a132-c9fe-48d1-9fa5-b654c3156977                                            username                :                arrangement:serviceaccount:api:api                      

The disquisitional data in the response is in the status object with the following fields:

  • Authenticated: the field is fix to true, which means the token was successfully validated.
  • In user object you lot tin can detect the following backdrop:
    • The username corresponding to the service business relationship used by the Pod - arrangement:serviceaccount:examination:sa-examination-1.
    • The uid for organisation user ID of the current user.
  • Groups includes the groups that the user belongs to.
  • Audiences contains a list of audiences that the token is intended for. In this example, only the api is a valid audience.

Excellent, yous just verified the Service Account token!

You know that:

  • The token is valid.
  • The identity of the caller (the API Service Business relationship).
  • The groups that the caller belongs to.

Since you can validate and verify any token, you could leverage the mechanism in your Information Shop component to authenticate and authorise requests!

Let's take a look at how you could include the above logic in your apps using the Kubernetes Become client.

Implementation of the services

Here's how the two services interact with each other and the Kubernetes API:

  1. At startup, an API component reads the Service Business relationship token and keeps it in memory.
  2. The API component calls the data store passing the token every bit an HTTP header — i.e. X-Customer-Id.
  3. When the data store receives a request, it reads the token from the 10-Client-Id header and issues a request to the Token Review API to check its validity.
  4. If the response is authenticated, the data store component replies with a successful message, otherwise a 401 fault.

The post-obit diagram represents the higher up call flow:

First, let'southward look at the implementation of the API service.

You can notice the application code in the file service_accounts/api/main.become.

The Service Business relationship Token is automatically mounted in /var/run/secrets/kubernetes.io/serviceaccount/token and you could read its value with:

main.become

                                          func                readToken                (                )                {                                            b,                err                :=                ioutil.                ReadFile                (                "/var/run/secrets/kubernetes.io/serviceaccount/token"                )                                            if                err                !=                nil                {                panic                (err)                }                                            serviceToken                =                string                (b)                                            }                                    

And then, the Service Token is passed on to the telephone call to the Secret store service in the X-Client-Id HTTP header:

main.go

                                          func                handleIndex                (w http.ResponseWriter,                r                *http.Request)                {                … client                :=                &http.Customer{                }                req,                err                :=                http.                NewRequest                (                "Become"                ,                serviceConnstring,                nil                )                if                err                !=                nil                {                panic                (err)                }                            req.Header.                Add                (                "X-Client-Id"                ,                serviceToken)                            resp,                err                :=                client.                Do                (req)                      

Every bit soon every bit the reply from the Secret store is received, it is so sent back as a response:

main.go

                          if                err                !=                nil                {                http.                Mistake                (w,                err.                Error                (                )                ,                http.StatusInternalServerError)                render                }                else                {                defer                resp.Body.                Shut                (                )                                            body,                _                :=                ioutil.                ReadAll                (resp.Body)                io.                WriteString                (w,                string                (trunk)                )                                            }                                    

The following YAML manifest is used to deploy the API service:

deployment.yaml

                                          apiVersion                :                v1                kind                :                Namespace                metadata                :                proper noun                :                api                ---                apiVersion                :                v1                kind                :                ServiceAccount                metadata                :                name                :                api                namespace                :                api                ---                apiVersion                :                apps/v1                kind                :                Deployment                metadata                :                name                :                app                namespace                :                api                spec                :                replicas                :                i                selector                :                matchLabels                :                app                :                api                template                :                metadata                :                labels                :                app                :                api                spec                :                                            serviceAccount                :                api                                            containers                :                -                proper noun                :                app                prototype                :                amitsaha/k8s-sa-volume-demo-api:sa-                1                env                :                -                name                :                LISTEN_ADDR                value                :                ":8080"                -                proper name                :                DATA_STORE_CONNSTRING                value                :                "http://app.data-shop.svc.cluster.local"                ports                :                -                containerPort                :                8080                ---                apiVersion                :                v1                kind                :                Service                metadata                :                name                :                app                namespace                :                api                spec                :                type                :                NodePort                selector                :                app                :                api                ports                :                -                port                :                8080                targetPort                :                8080                                    

You will notice that in that location is zip special about the Deployment manifest above autonomously from having a Service Account associated with it.

Let's movement onto the data shop service.

You can discover the complete application in service_accounts/data-store/main.go.

The data shop service does ii primal things:

  1. It retrieves the value of the X-Client-Id header from the incoming asking.
  2. It then invokes the Kubernetes Token Review API to bank check if the token is valid.

Step (1) is performed by the following lawmaking:

main.get

                          clientId                :=                r.Header.                Get                (                "X-Client-Id"                )                                            if                len                (clientId)                ==                0                {                http.                Fault                (w,                "Ten-Client-Id not supplied"                ,                http.StatusUnauthorized)                return                }                                    

And then, pace (two) is performed using the Kubernetes Go customer.

Start, we create a ClientSet object:

primary.go

                          config,                err                :=                rest.                InClusterConfig                (                )                clientset,                err                :=                kubernetes.                NewForConfig                (config)                                    

The InClusterConfig() function automatically reads the Service Account Token for the Pod, and hence you do not have to specify the path manually.

Then, you construct a TokenReview object specifying the token yous desire to validate in the Token field:

main.go

                          tr                :=                authv1.TokenReview{                Spec:                authv1.TokenReviewSpec{                Token:                clientId,                }                ,                }                                    

Finally, you can create a TokenReview request with:

main.go

                          result,                err                :=                clientset.                AuthenticationV1                (                )                .                TokenReviews                (                )                .                Create                (ctx,                &tr,                metav1.CreateOptions{                }                )                                    

The post-obit YAML manifest volition create the various resources needed for the data store service:

deployment.yaml

                                          apiVersion                :                v1                kind                :                Namespace                metadata                :                name                :                data-store                ---                apiVersion                :                v1                kind                :                ServiceAccount                metadata                :                name                :                data-store                namespace                :                information-shop                ---                                            apiVersion                :                rbac.authorization.k8s.io/v1                kind                :                ClusterRoleBinding                metadata                :                name                :                function-tokenreview-bounden                roleRef                :                apiGroup                :                rbac.authorization.k8s.io                kind                :                ClusterRole                name                :                organisation:auth-delegator                subjects                :                -                kind                :                ServiceAccount                proper noun                :                information-shop                namespace                :                data-store                                            ---                apiVersion                :                apps/v1                kind                :                Deployment                metadata                :                name                :                app                namespace                :                information-shop                spec                :                replicas                :                1                selector                :                matchLabels                :                app                :                information-store                template                :                metadata                :                labels                :                app                :                data-store                spec                :                serviceAccount                :                information-store                containers                :                -                name                :                app                image                :                amitsaha/k8s-sa-book-demo-ss:sa-                one                env                :                -                name                :                LISTEN_ADDR                value                :                ":8081"                ports                :                -                containerPort                :                8081                ---                apiVersion                :                v1                kind                :                Service                metadata                :                proper noun                :                app                namespace                :                data-store                spec                :                selector                :                app                :                data-store                ports                :                -                protocol                :                TCP                port                :                eighty                targetPort                :                8081                                    

Compared to the API service, the data store service requires a ClusterRoleBinding resource to be created, which assembly the information-store Service Account to the system:auth-delegator ClusterRole.

Go back to the terminal session where you lot deployed the information store service and inspect the logs:

bash

                          kubectl --namepsace data-store logs                <data-store-pod-id>                                            2020/11/26 03:17:43                {                "authenticated"                :                true,                "user"                :                {                "username"                :                "organisation:serviceaccount:api:api",                "uid"                :                "a693c26c-1b2e-47d0-a026-21802365f8d4",                "groups"                :                [                "system:serviceaccounts",                "system:serviceaccounts:api",                "organization:authenticated"                ]                },                "audiences"                :                [                "api"                ]                }                                                  

The output is a Go construction version of the JSON response you saw earlier.

Thus, yous meet how the API component reads the Service Business relationship Token and passes it to the Data shop equally a mode to authenticate itself.

The Data shop service retrieves the token and checks it with the Kubernetes API.

When valid, the Data shop component allows the request from the API service to be processed.

The implementation works well, only information technology suffers from three drawbacks:

Ane Hush-hush for every Service Account

When you create a Service Business relationship, Kubernetes creates a companion Secret object with a token.

You use the token to cosign with the Kubernetes API.

In this example, you tin inspect the Service Account and discover the token with:

fustigate

                          kubectl --namespace api describe serviceaccount api                            Name:                api Namespace:           api Mountable secrets:   api-token-ttr8q Tokens:              api-token-ttr8q                                    

Which matches the Secret object in the namespace:

bash

                          kubectl go secrets --namespace api                            NAME                  Blazon api-token-ttr8q       kubernetes.io/service-account-token default-token-vppc9   kubernetes.io/service-account-token                                    

However, any workload that can read a hugger-mugger in a namespace can also read the Service Account tokens in the same namespace.

In other words, you could take whatsoever other Pod using the aforementioned Service Account to cosign against the Kubernetes API — effectively impersonating someone else.

Unfortunately, at that place's no mechanism to restrict access to a subset of Secrets in a namespace.

The application has access to all of them, or none of them.

Yous could create a namespace for every app and store a Service Account in it, simply that's frequently overkilled.

Long live the Service Business relationship's token

The tokens associated with a Service Account are long-lived and exercise not expire.

In other words, once yous have access to one of them, y'all can use information technology forever (or until the administrator deletes the Secret associated with the token).

You could manually rotate identities by manually removing and re-assigning Service Accounts.

If it sounds similar a lot of work, information technology's because it is.

No audience binding of the tokens

As a cluster administrator, you cannot acquaintance a token with a specific audience.

Anyone with access to the Service Account token tin cosign with the Kubernetes API and is authorised to communicate with any other service running inside the cluster.

The destination service doesn't have whatever style to verify whether the token information technology was presented with was meant for itself at all.

As an example, imagine buying a ticket for a flight from London to New York.

If you buy a ticket from British Airways, you lot tin't employ the ticket to board a Virgin Atlantic flying.

Your ticket is leap to a particular audience (British Airways).

But in the example of Kubernetes, the same ticket (token) tin be used with whatever airline (audience).

You could solve both challenges past implementing solutions such as mutual TLS or using a JWT based solution with a key authority server.

All the same, in Kubernetes, you can use the Service Account Token Book Project characteristic to create fourth dimension-bound and audition-specific Service Account Tokens which do not persist in the cluster shop.

The Kubernetes API server acts as the cardinal authority server, and y'all don't accept to worry about expiring tokens.

This feature was introduced in Kubernetes 1.12 and gained further improvements in 1.thirteen and provides a more than secure alternative to workload-specific service accounts.

This will be promoted to a GA feature in the upcoming Kubernetes one.20 release.

In the next part of the article, yous will re-implement the same lawmaking for authenticating apps using the Service Account Token Book Projection.

Information technology's a good idea to clean upwards the two namespaces with:

bash

                          kubectl delete namespace api                            namespace                "api"                deleted                            kubectl delete namespace data-shop                            namespace                "data-store"                deleted                                    

Inter-Service authentication using Service Account Token Volume Projection

The Service Account Tokens made available to workloads via the Service Account Token Volume Projection (ProjectedServiceAccountToken) are time-limited, audience leap and are not associated with surreptitious objects.

If a Pod is deleted or the Service Account is removed, these tokens become invalid, thus preventing whatsoever misuse.

A serviceAccountToken book projection is one of the projected volume types.

A projected volume is a book that mounts several existing volumes into the same directory.

When this volume blazon is added to a Pod, the Service Business relationship Token is mounted on the filesystem — in the same way that the Service Account Tokens are mounted.

There's a difference though.

The kubelet automatically rotates the token when it's well-nigh to elapse.

In addition, you can configure the path at which yous want this token to be available.

Allow's come across how you tin improve the API component to include the Service Account Token Volume Projection.

The API component

You can read the Service Account Token mounted via book project with:

main.become

                          b,                err                :=                ioutil.                ReadFile                (                "/var/run/secrets/tokens/api-token"                )                serviceToken                =                string                (b)                                    

Annotation how the path to the Service Account Token is different from the previous case (i.east. it used to be /var/run/secrets/kubernetes.io/serviceaccount/token).

Since the Service Account Token Volume Projection feature relies on the token being refreshed periodically by the kubelet, information technology is recommended to re-read the token every v minutes in the app.

You can accomplish this via a ticker in Get as follows:

main.go

                          ticker                :=                time.                NewTicker                (                300                *                fourth dimension.Second)                washed                :=                brand                (                chan                bool                )                go                func                (                )                {                for                {                select                {                case                <-done:                return                case                <-ticker.C:                readToken                (                )                }                }                }                (                )                                    

The readToken() role reads the file, /var/run/secrets/tokens/api-token and sets the global variable, serviceToken to the token value.

If y'all are non familiar with Get'south ticker, think of a ticker every bit a background thread which runs a part at periodic intervals.

You tin find the entire application code in service_accounts_volume_projection/api/chief.go.

Now, let's deploy this service.

You will apply that image in the deployment manifest (service_accounts_volume_projection/api/deployment.yaml):

deployment.yaml

                                          apiVersion                :                v1                kind                :                Namespace                metadata                :                name                :                api                ---                apiVersion                :                v1                kind                :                ServiceAccount                metadata                :                name                :                api                namespace                :                api                ---                apiVersion                :                apps/v1                kind                :                Deployment                metadata                :                name                :                app                namespace                :                api                spec                :                replicas                :                i                selector                :                matchLabels                :                app                :                api                template                :                metadata                :                labels                :                app                :                api                spec                :                serviceAccount                :                api                                            volumes                :                -                name                :                api-token                projected                :                sources                :                -                serviceAccountToken                :                path                :                api-token                expirationSeconds                :                600                audience                :                data-shop                containers                :                                            -                name                :                app                paradigm                :                amitsaha/k8s-sa-volume-demo-api:sa-                2                env                :                -                name                :                LISTEN_ADDR                value                :                ":8080"                -                name                :                DATA_STORE_CONNSTRING                value                :                "http://app.information-store.svc.cluster.local"                ports                :                -                containerPort                :                8080                volumeMounts                :                -                mountPath                :                /var/run/secrets/tokens                name                :                api-token                ---                apiVersion                :                v1                kind                :                Service                metadata                :                name                :                app                namespace                :                api                spec                :                blazon                :                NodePort                selector                :                app                :                api                ports                :                -                port                :                8080                targetPort                :                8080                                    

A book named api-token of projected type will be created with the source beingness serviceAccountToken.

The book defines three boosted backdrop:

  1. The path where the token will be available inside the configured volume.
  2. The audience field specifies what the intended audition for the token is (if not specified, it defaults to api).
  3. The expirationSeconds betoken how long a token is valid for - the minimum is 600 seconds or x minutes.

Please notice how the audience field specifies that this Service Account Token is allowed to communicate only with services that identify themselves as a data-store.

If y'all omit data-store as an audience in the Secret store component, the API won't be able to talk to it — it's not its audition!

Note that if you are deploying a Pod to use this feature in a cluster with Pod Security Policies enforced, you will demand to ensure that the projected book blazon is allowed.

You can create a new API deployment with:

fustigate

                          kubectl apply -f service_accounts_volume_projection/api/deployment.yaml                            namespace/api created serviceaccount/api created deployment.apps/app created service/app created                                    

Call up the URL of the API service with:

bash

                          minikube --namespace api                service                app --url                            http://192.168.99.101:31541                                    

Y'all can consequence a request with:

bash

                                          curl                http://192.168.99.101:31541                            Get                "http://app.data-store.svc.cluster.local"                :                dial tcp: lookup app.data-store.svc.cluster.local: no such                host                                                  

This is expected as the data shop is non yet deployed.

Keep the concluding open up.

Side by side, let's modify and deploy the data store service.

Data Store

The token review payload for the information store will now be every bit follows:

main.go

                          tr                :=                authv1.TokenReview{                pec:                authv1.TokenReviewSpec{                Token:                clientId,                Audiences:                [                ]                string                {                "data-store"                }                ,                }                ,                }                                    

Now, in the TokenReview object, the Information store explicitly passes data-store as the audition.

If the token doesn't include information-shop as an audition, the Token Review API will not authorise the request.

In other words, the Information store service tin assert the identity of the caller and validate that the incoming request token was meant for the data shop service.

You lot tin find the entire application code in service_accounts_volume_projection/data-store/main.go.

Adjacent, allow'southward deploy this service.

Yous tin can create the deployment with:

fustigate

                          kubectl apply -f service_accounts_volume_projection/information-store/deployment.yaml                            namespace/data-store created serviceaccount/data-store created clusterrolebinding.rbac.say-so.k8s.io/role-tokenreview-binding created deployment.apps/app created service/app created                                    

Let's cheque if the service is upwards and running correctly:

bash

                          kubectl --namespace data-store depict                service                app                            Name:           app Namespace:      data-store Labels:                <none>                Selector:                app                =data-shop Type:           ClusterIP IP:                x.106.239.243 Port:                <unset>                lxxx/TCP TargetPort:                8081/TCP Endpoints:                172.18.0.5:8081                                    

The value of Endpoints in the output in a higher place tells us that app is now upward and running.

Now, use curl to brand a request to the API service again:

bash

                                          scroll                http://192.168.99.101:31541                            Hello from information store. You lot have been authenticated                                    

Yous should inspect the logs of the Clandestine shop with:

bash

                          kubectl --namespace information-shop logs                <pod id>                                            2020/11/26 02:04:51                {                UID:ec7c304f-9722-4d1b-9f67-d3ce32cd8d4c,                "authenticated"                :                true, Groups:[organisation:serviceaccounts system:serviceaccounts:api system:authenticated],                "user"                :                {                Extra:map[string]ExtraValue{authentication.kubernetes.io/pod-proper name:                "username"                :                "system:serviceaccount:api:api",                [app-65d954658c-dbbr5],                "uid"                :                "0d32dccd-3d84-4955-b6e8-bbc362debb52", hallmark.kubernetes.io/pod-uid:                [1b37a3f4-54f1-419c-b435-affce3f4a0f3],},},                "groups"                :                [                Mistake:,Audiences:[data-store],}                "system:serviceaccounts",                "arrangement:serviceaccounts:api",                "system:authenticated"                ],                "extra"                :                {                "authentication.kubernetes.io/pod-name"                :                [                "app-649cfb884b-hxzzj"                ],                "authentication.kubernetes.io/pod-uid"                :                [                "a4c967a0-2b57-4f1f-aabc-6aea2dc15098"                ]                }                },                "audiences"                :                [                "data-store"                ]                }                                                  

In you switch to the logs of the API service, yous should meet the following lines that demonstrate when the Service Account Token is re-read from the filesystem:

bash

                                          2020/08/26 05:03:43 Refreshing                service                account token                2020/08/26 05:xiii:42 Refreshing                service                business relationship token                2020/08/26 05:eighteen:42 Refreshing                service                account token                                    

Summary

Service Account Token Volume project allows you to associate non-global, fourth dimension-bound and audience bound service tokens to your Kubernetes workloads.

In this article, you saw an case of using it for authentication between your services and how information technology is a better alternative to using the default Service Account Tokens.

Kubernetes native software such as Linkerd and Istio are embracing it for their internal communication and managed Kubernetes service providers such as GKE and AWS EKS are using this project volume type to enable more robust pod identity systems.

Learn more

  • Kubernetes Hallmark
  • Kubernetes Service Account Token Book Projection

Exist the showtime to be notified when a new commodity or Kubernetes experiment is published.

*We'll never share your email address, and you can opt-out at whatsoever time.

Source: https://learnk8s.io/microservices-authentication-kubernetes

Posted by: kisertany1937.blogspot.com

Related Posts

0 Response to "How To Check Web Service Is Up And Running"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel