OpenShift Service Accounts

Learn how Service Accounts work in OpenShift, understand application identity, authentication, API access, RBAC integration, and secure Spring Boot applications using Service Accounts.


Introduction

When developers log in to OpenShift, they authenticate using a User Account.

However, applications running inside Pods are not human users. They also need an identity to:

  • Read ConfigMaps
  • Access Secrets
  • Call the Kubernetes API
  • Communicate with other OpenShift resources
  • Authenticate securely without hardcoded credentials

This identity is called a Service Account.

Every Pod running inside OpenShift executes using a Service Account.

Instead of embedding usernames and passwords inside applications, OpenShift automatically provides secure authentication through Service Accounts.


Learning Objectives

By the end of this article, you will understand:

  • What is a Service Account?
  • Why Service Accounts are required
  • Service Account architecture
  • Default Service Account
  • Creating custom Service Accounts
  • RBAC integration
  • Spring Boot API access
  • Enterprise security best practices

Why Service Accounts?

Imagine a Spring Boot application that needs to read a ConfigMap.

Without a Service Account:

flowchart LR
    A[Spring Boot]
    --> B[Kubernetes API]

    B --> C[❌ Authentication Failed]

The Kubernetes API doesn't know the application's identity.


Solution

Assign a Service Account.

flowchart LR
    A[Spring Boot Pod]
    --> B[Service Account]

    B --> C[Kubernetes API]

    C --> D[ConfigMaps]

    C --> E[Secrets]

The application now has a secure identity.


What is a Service Account?

A Service Account is a Kubernetes/OpenShift resource that provides an identity for Pods.

Unlike a User Account:

User Account Service Account
Human Application
Interactive Login Automatic Authentication
OAuth / LDAP Kubernetes Token
Used by Developers Used by Pods

Service Account Architecture

flowchart TD

Pod[Spring Boot Pod]

SA[Service Account]

API[Kubernetes API]

Secrets[Secrets]

ConfigMaps[ConfigMaps]

Pod --> SA

SA --> API

API --> Secrets

API --> ConfigMaps

Authentication Flow

sequenceDiagram

participant Pod

participant ServiceAccount

participant KubernetesAPI

participant Secret

Pod->>ServiceAccount: Request Token

ServiceAccount->>KubernetesAPI: Authenticate

KubernetesAPI-->>Pod: Authentication Success

Pod->>Secret: Read Secret

Default Service Account

Every namespace automatically contains a default Service Account.

Verify:

oc get serviceaccounts

Example:

NAME

default

builder

deployer

OpenShift automatically assigns the default Service Account unless another one is specified.


Built-in Service Accounts

Service Account Purpose
default Application Pods
builder BuildConfig builds
deployer Deployment operations

View Service Accounts

oc get sa

Describe:

oc describe sa default

Create Service Account

apiVersion: v1
kind: ServiceAccount

metadata:
  name: payment-service-account

Deploy:

oc apply -f service-account.yaml

Verify Service Account

oc get serviceaccounts

Example:

NAME

default

payment-service-account

Assign Service Account

Deployment YAML

spec:

  template:

    spec:

      serviceAccountName: payment-service-account

Every Pod created from this Deployment uses the specified Service Account.


Deployment Architecture

flowchart LR

Deployment

--> Pod1

Deployment

--> Pod2

Pod1

--> ServiceAccount

Pod2

--> ServiceAccount

Service Account Token

Each Service Account receives a secure authentication token.

flowchart LR

ServiceAccount

--> Token

Token

--> KubernetesAPI

The token is automatically mounted inside the Pod.


Token Location

Inside the Pod:

/var/run/secrets/kubernetes.io/serviceaccount/

Files include:

token

namespace

ca.crt

Verify Token

Open Pod.

oc rsh payment-api-xxxxx

View:

ls /var/run/secrets/kubernetes.io/serviceaccount

Spring Boot Example

Suppose the application needs to read ConfigMaps.

Dependency:

<dependency>

    <groupId>io.fabric8</groupId>

    <artifactId>kubernetes-client</artifactId>

</dependency>

Read ConfigMap

KubernetesClient client =
    new KubernetesClientBuilder().build();

ConfigMap configMap =
    client.configMaps()
          .inNamespace("payments")
          .withName("payment-config")
          .get();

Authentication happens automatically using the mounted Service Account token.


Service Account + RBAC

A Service Account has no permissions by default.

Permissions are granted using RBAC.

flowchart LR

ServiceAccount

--> RoleBinding

RoleBinding

--> Role

Role

--> ConfigMaps

Create Role

apiVersion: rbac.authorization.k8s.io/v1
kind: Role

metadata:
  name: config-reader

rules:

- apiGroups: [""]

  resources:

  - configmaps

  verbs:

  - get

  - list

Create RoleBinding

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding

metadata:
  name: payment-binding

subjects:

- kind: ServiceAccount

  name: payment-service-account

roleRef:

  kind: Role

  name: config-reader

  apiGroup: rbac.authorization.k8s.io

Permission Flow

flowchart LR

SpringBoot

--> ServiceAccount

ServiceAccount

--> RoleBinding

RoleBinding

--> Role

Role

--> ConfigMaps

Banking Example

flowchart TD

PaymentService

--> PaymentSA[Payment Service Account]

PaymentSA

--> PaymentSecrets

PaymentSA

--> PaymentConfig

PaymentSA

-. Cannot Access .-> LoanNamespace

Every microservice has its own Service Account.


Microservice Architecture

flowchart LR

PaymentService

--> PaymentSA

CustomerService

--> CustomerSA

NotificationService

--> NotificationSA

PaymentSA

--> PaymentSecrets

CustomerSA

--> CustomerSecrets

NotificationSA

--> NotificationSecrets

Applications have isolated identities.


Service Account Isolation

Never share one Service Account across unrelated applications.

flowchart TD

PaymentApp

--> PaymentSA

CustomerApp

--> CustomerSA

InventoryApp

--> InventorySA

This minimizes security risks.


Verify Current Service Account

oc describe pod payment-api

Look for:

Service Account:

payment-service-account

Check Permissions

oc auth can-i get configmaps \
--as system:serviceaccount:payments:payment-service-account

Expected:

yes

Common Problems

Forbidden Error

Example:

Error from server (Forbidden)

Possible causes:

  • Missing Role
  • Missing RoleBinding
  • Wrong Service Account

Service Account Not Used

Check Deployment.

oc describe deployment payment-api

Verify:

serviceAccountName

Cannot Read Secrets

Verify RBAC.

oc auth can-i get secrets

Enterprise Architecture

flowchart TD
    USERS["Users"]
    ROUTE["OpenShift Route"]
    GATEWAY["API Gateway"]

    PAYMENT["Payment Service"]
    SA["Payment Service Account"]

    CONFIG["ConfigMaps"]
    SECRETS["Secrets"]
    DB["PostgreSQL"]

    USERS --> ROUTE
    ROUTE --> GATEWAY
    GATEWAY --> PAYMENT

    PAYMENT --> SA
    SA --> CONFIG
    SA --> SECRETS

    PAYMENT --> DB

Best Practices

  • Create one Service Account per microservice.
  • Follow the Principle of Least Privilege.
  • Avoid using the default Service Account in production.
  • Grant only required permissions.
  • Rotate Service Account tokens where applicable.
  • Audit Service Account permissions regularly.
  • Never grant cluster-admin to applications.
  • Use separate Service Accounts for CI/CD pipelines.

Common Mistakes

❌ Using the default Service Account for every application.

❌ Sharing one Service Account across multiple services.

❌ Granting excessive permissions.

❌ Embedding Kubernetes credentials inside source code.

❌ Using cluster-admin for application Pods.


Advantages

  • Secure application identity
  • Automatic authentication
  • RBAC integration
  • Least-privilege access
  • Better auditing
  • No hardcoded credentials
  • Enterprise security
  • Cloud-native authentication

Summary

Service Accounts provide the identity that applications use inside OpenShift.

Key takeaways:

  • Every Pod runs using a Service Account.
  • Service Accounts authenticate applications to the Kubernetes API.
  • RBAC controls what a Service Account can access.
  • Each microservice should have its own dedicated Service Account.
  • Avoid using the default Service Account for production workloads.
  • Combining Service Accounts with RBAC creates a secure and scalable authorization model.

Interview Questions

  1. What is a Service Account?
  2. Why do applications need Service Accounts?
  3. What is the difference between a User Account and a Service Account?
  4. Where is the Service Account token mounted inside a Pod?
  5. How do you assign a Service Account to a Deployment?
  6. How are permissions granted to a Service Account?
  7. Why should every microservice have its own Service Account?
  8. What are the built-in Service Accounts in OpenShift?
  9. How do you verify the Service Account used by a Pod?
  10. What are the best practices for using Service Accounts?