Microservices architecture is becoming a prominent design principle and a service development methodology, we have now started to see many microservices in production. Yet, security is a less concerned aspect, most of the time development teams are much focus on edge security but due to distributed and disposable nature of microservices, it's equally important to pay attention to securing service-to-service communication both during the transmission and sharing end-user context among services in order to cover vast attack surface.
8. Edge Security Authorization
• OAuth2 scopes of a token are validated against access
control policies.
• How to make policy decisions?
• Delegating to central PDP
• Caching policy decisions can reduce latency.
• Embedded PDP
• Get policy updates from PAP based on
polling or listing to push events from PAP
• Can be embedded agent or sidecar agent
• Policy implementations
• XACML
• OPA
10. Edge Security Passing end-user context
• JWT token as a header
• Injecting user context to the message body.
11. Securing inter-service communication
1. Passing end-user identity
1. Passing self-issued JWT
• Not recommended
2. Passing JWT received from the Gateway
• Pass the Gateway token
• Pass Gateway token within a nested-JWT
3. Get a JWT from a STS and pass
13. Securing inter-service communication
2. Passing service identity
• Trust the network level security
• Simple
• Violates zero-trust, Defense in-depth, and secure-by-design/default principles
• JWT
• Can be used to send end-user context and sending service identity (based on signature)
• sub - provide the identity of the owner ( unique id for a given issuer )
• aud - specifies the intended audience
• iss - identity of the issuer
• Signing and verification are based on JWS
• Key provision and management are required
• Caching can be used to reduce the cost of JWT signature validation
• Mutual TLS (mTLS)
• Complex to setup and maintain
• Very secure
14. Securing inter-service communication
Self-issued JWT JWT from GW JWT from STS No user context
Self-issued JWT NO OK OK OK
mTLS NO OK OK OK
Network NO NO No NO
Passing the end-user context
Passing the
service identity
15. Securing inter-service communication - JWT
1. Establish the key infrastructure
a) Generate a Certificate Authority (CA) , all the
microservices will trust this.
b) Generate a key-pair for order-processing
microservice (order-processing.jks)
c) Generate a key-pair for inventory microservice
(inventory.jks)
d) Sign both order-processing and inventory
certificates from above created CA.
17. Securing inter-service communication - JWT
3. JWT signing and verification
a) The first service generate a JWT and sign it before sending ( self-issued JWT)
b) The receiving service validates the signature and decide to accept/reject based on root
certificate verification.
Sanders's signature can be used to
• Establish an identity of sending
service
• Establish trust-based on root
certificate
19. Securing inter-service communication - mTLS
1. Establish the key infrastructure
a) Generate a Certificate Authority (CA) , all the
microservices will trust this.
b) Generate a key-pair for order-processing
microservice (order-processing.jks)
c) Generate a key-pair for inventory microservice
(inventory.jks)
d) Sign both order-processing and inventory
certificates from above created CA.
21. Example : mTLS for inter-service communication
3. Establishment of secure SSL channel
• After two services authenticate with each other, they establish a secure SSL channel for
message communication; usually this task is a responsibility of the transport layer of the
service.
• The mutual authentication is based on trusting the root certificate which is common for all the
services.
22. 1.Trust bootstrap
• Inject credentials during the CICD phase
• Trust a known member
2.Provisioning of keys & certificates to microservices
• Inject credentials during the CICD phase
• Request credentials during the bootstrap time.
3.Key revocation
• Short-lived certificate instead of CRL, OCSP, OCSP Stapling
4.Key rotation
• Automated key rotation
Key Infrastructure challengers
23. • A set of open-source standards for securely identifying software systems in
dynamic and heterogeneous environments.
• SPIFFE defines short-lived cryptographic identity documents (SVIDs), workloads
can use SVIDs when authenticating to other workloads; for example, by
establishing a TLS connection or by signing and verifying a JWT token.
• Comprises three major components
1. SPIFFE ID
2. SPIFFE Verifiable Identity Document (SVID) - X.509-SVID and JWT-SVID
3. Workload API
SPIFFE
24. SPIFFE - SPIFFE ID
• A SPIFFE ID is a structured string (represented as a URI) which serves as the
"name" of an entity.
• Format : spiffe://trust domain/workload identifier
25. SPIFFE Verifiable Identity Document (SVID)
• A SPIFFE Verifiable Identity Document (SVID) is the mechanism through which a
workload communicates its identity to a resource or caller.
• An SVID is considered valid if it has been signed by an authority within the SPIFFE
ID's trust domain.
• A signing authority MUST exist in each trust domain, and this signing authority
MUST carry an SVID of its own.
• SVID comprises three basic components:
• A SPIFFE ID
• A valid signature
• Public key
26. SPIFFE Verifiable Identity Document (SVID)
• Currently support 2 formats
• X509 SPIFFE SVID
• JWT SPIFFE SVID
• The specification also defines
• The SPIFFE Trust Domain and Bundle
• The SPIFFE Workload Endpoint and API
27. SPIRE – How it works
1. Node agent authenticates with the SPIRE
server and send node identity document.
2. Node attestor in the SPIRE server
validates the provided identification
document and returns set of SPIFFE IDs and
selectors.
3. The Workload requires it’s identity from
the Node Agent.
4. Node Agent decides on the SPIFFE ID to
be given to workload. It generates a key
pair based on that and sends the CSR to the
SPIRE server. (e.g - process ID )
28. SPIRE – How it works
5. Server responds to the node agent with
the signed SVID for the workload along
with the trust bundles, indicating which
this workload can trust other loads.
6. Certificate bundle is returned to the
workload.
29. SPIRE – How it works
https://www.slideshare.net/QAware/building-trust-between-modern-distributed-systems-with-spiffe-88969318
36. Docker Swaram
• The manager node generates a new self-signed root Certificate Authority
(CA) along with a key pair, which are used to secure communications with
other nodes.
• Each time a new node joins, it send CSR to the manager and , the manager
issues a certificate to the node. The certificate contains a randomly
generated node ID.
JWT Header :
The gateway can sign the JWT so that receivers can validate the signature for identity verification
How to pass valid JWT to the backend ?
1. The gateway can have number of identity values in the ‘aud’ claim, these identity values are pre-agreed identifies of services that intended to use the JWT token.
2. The above approach assumed that G/W pre-assumed all the down-stream microservices in the particular flow, instead of this it’s possible to use Token Exchange with a STS to get a new token for target service.
When passing a JWT token generated by the G/W from one service to another ( not the G/W to a service, G/W -> Service A -> Service B) , the sending service can sign the JWT; if signed receiving service can verify the identity of sending service otherwise receiving service can’t verify the identify of sending service, it only can verify end-user context based on G/W signature verification. ( in this case it use nested JWT)
How this works when these two services from 2 trust domains
1. Service-A present it’s current token received from GW to STS of A-domain and request a token which audience set to STS of B-Domain, then contact STS or domain-B with this new token and request another token to access service-B
2. Service-A present it’s current token received from GW to STS of A-domain and request a token which audience set to G/W of B-Domain, then call the service-B via G/W of domain-B with this token
In practice, most of the cases self-issues JWT is used over TLS where JWT provides authentication while TLS provides confidentiality and integrity.
In practice, most of the cases self-issues JWT is used over TLS where JWT provides authentication while TLS provides confidentiality and integrity.
In practice, most of the cases self-issues JWT is used over TLS where JWT provides authentication while TLS provides confidentiality and integrity.
This JWT use case is known as self-issued JWT, note that this can be only used to authenticate identity of the sending service, this can bot be the best method to pass end-user context to another service unless there is great level of trust (usually within same trust domain ) among services. One of the following approaches best suite for these use cases…
1. The better approach is use the singed JWT token received from the G/W as the source and create a nested JWT by signing with calling services private key so that receiving service can verify both the end-user identity and sending service’s identity, in case there is no token from G/W sending service can get a token from a STS for signing.
2. Use mTLS for service authentication and use pass JWT from G/W for end-user identity
3. Use mTLS for service authentication and get a token from a STS to pass in the other service.
-The SPIFFE ID of the signing authority SHOULD reside in the trust domain in which it is authoritative, and SHOULD NOT have a path component. The SVID of the signing authority then forms the basis of trust for a given trust domain.
Chaining of trust, if desired, can be achieved by signing the authority’s SVID with the private key of a foreign trust domain’s authority. In the event that trust is not being chained, then the authority’s SVID is self-signed.
REF :
https://github.com/spiffe/spiffe/blob/master/standards/SPIFFE-ID.md#3-spiffe-verifiable-identity-document
https://github.com/spiffe/spiffe/tree/master/standards
https://gist.github.com/Pushpalanka/b70d5057154eb3c34d651e6a4d8f46ee
https://spiffe.io/spire/overview/#all-about-the-server
an AWS Instance Identity Document to the server.
Istio tunnels service-to-service communication through the client side and server side Envoy proxies. For a client to call a server with mutual TLS authentication
Istio re-routes the outbound traffic from a client to the client’s local sidecar Envoy.
The client side Envoy starts a mutual TLS handshake with the server side Envoy.
During the handshake, the client side Envoy also does a secure naming check to verify that the service account presented in the server certificate is authorized to run the target service.
The client side Envoy and the server side Envoy establish a mutual TLS connection, and Istio forwards the traffic from the client side Envoy to the server side Envoy.
After authorization, the server side Envoy forwards the traffic to the server service through local TCP connections.
By default, Citadel generates self-signed root certificate and key, and uses them to sign the workload certificates. Citadel can also use the operator-specified certificate and key to sign workload certificates.
Citadel watches the Kubernetes API server, creates a SPIFFE certificate and key pair for each of the existing and new service accounts then Citadel stores the certificate and key pairs as Kubernetes secrets.
When you create a pod, Kubernetes mounts the certificate and key pair to the pod according to its service account via Kubernetes secret volume.
Citadel watches the lifetime of each certificate, and automatically rotates the certificates by rewriting the Kubernetes secrets.
Pilot generates the secure naming information, which defines what service account or accounts can run a certain service. Pilot then passes the secure naming information to the sidecar Envoy.
Problems:
Private key is generated by Citadel not that secure
Key provisioning can happen over a network
Keys are stored in Pod file system so process can see
Certificates/Keys are loaded from file system to memory so each key rotation result into reload at Envoy proxy
1. Citadel creates a gRPC service to take CSR requests.
2. Envoy sends a certificate and key request via Envoy secret discovery service (SDS) API.
3. Upon receiving the SDS request, the node agent creates the private key and CSR before sending the CSR with its credentials to Citadel for signing.
4. Citadel validates the credentials carried in the CSR and signs the CSR to generate the certificate.
5. The node agent sends the certificate received from Citadel and the private key to Envoy via the Envoy SDS API.
6. The above CSR process repeats periodically for certificate and key rotation.
Envoy to node-agent communication via Unix Socket
Certificates/Keys are directly loaded into memory - secure and effective (no longer require reloading)
Private key generation happen at node-agent locally
Less bound with Kubernetes
REF:
https://www.youtube.com/watch?v=pKN4x4uXswU
https://www.cncf.io/blog/2019/04/25/simplifying-microservices-security-with-a-service-mesh/
https://istio.io/docs/concepts/security/
https://cilium.io/blog/2018/08/07/istio-10-cilium/
https://istio.io/docs/tasks/security/authn-policy/
https://www.youtube.com/watch?v=Sx2luXC3kSU&t=2722s
https://www.youtube.com/watch?v=eOI2aM9P7-c&t=2461s
https://www.youtube.com/watch?v=GnjwaTcNKK4&t=185s
https://www.youtube.com/watch?v=NiiZOszksGU
https://www.youtube.com/watch?v=QlQyqCaTOh0
“docker swarm init” - Docker designates itself as a manager node. By default, the manager node generates a new self-signed root Certificate Authority (CA) along with a key pair, which are used to secure communications with other nodes that join the swarm. However, it is possible to provide external CA as well that can be cooperate level or public CA.
The manager node also generates two tokens to use when you join additional nodes to the swarm: one worker token and one manager token. Each token includes the digest of the root CA’s certificate and a randomly generated secret.
When a node joins the swarm, the joining node uses the digest to validate the root CA certificate from the remote manager and generate key pairs then submit CSR. The remote manager uses the secret to ensure the joining node is an approved node.
Each time a new node joins the swarm, the manager issues a certificate to the node. The certificate contains a randomly generated node ID to identify the node under the certificate common name (CN) and the role under the organizational unit (OU). The node ID serves as the cryptographically secure node identity for the lifetime of the node in the current swarm.
REF:
https://docs.docker.com/engine/swarm/how-swarm-mode-works/pki/
https://www.infoq.com/presentations/tls-swarm-pki/
https://www.youtube.com/watch?v=apma_C24W58