blob: ad675acb7c7ef7dc6aaee2e30fac9c3febf37533 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Apache Cassandra | Apache Cassandra Documentation</title>
<link rel="stylesheet" href="../../assets/css/site.css">
<meta name="description" content="The Apache Cassandra Community">
<link rel="schema.dcterms" href="https://purl.org/dc/terms/">
<meta name="dcterms.subject" content="_">
<meta name="dcterms.identifier" content="master">
<meta name="generator" content="Antora 2.3.4">
<link rel="icon" href="../../assets/img/favicon.ico" type="image/x-icon">
<script>
const script = document.createElement("script");
const domain = window.location.hostname;
script.type = "text/javascript";
script.src = "https://plausible.cassandra.apache.org/js/plausible.js";
script.setAttribute("data-domain",domain);
script.setAttribute("defer",'true');
script.setAttribute("async",'true');
document.getElementsByTagName("head")[0].appendChild(script);
</script> </head>
<body class="single-post">
<div class="container mx-auto relative">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<meta property="og:type" content="website" />
<meta property="og:description" content="" />
<meta property="og:url" content="/" />
<meta property="og:site_name" content="Apache Cassandra" />
<header id="top-nav">
<div class="inner relative">
<div class="header-social-icons text-right">
<a href="https://twitter.com/cassandra?lang=en" target="_blank" styles="margin-left: 20px;"><img src="../../assets/img/twitter-icon-circle-white.svg" alt="twitter icon" width="24"></a>
<a href="https://www.linkedin.com/company/apache-cassandra/" target="_blank" styles="margin-left: 20px;"><img src="../../assets/img/LI-In-Bug.png" alt="linked-in icon" width="24"></a>
<a href="https://www.youtube.com/c/PlanetCassandra" target="_blank" styles="margin-left: 20px;"><img src="../../assets/img/youtube-icon.png" alt="youtube icon" width="24"></a>
</div>
<div class="cf">
<div class="logo left"><a href="/"><img src="../../assets/img/logo-white-r.png" alt="cassandra logo"></a></div>
<div class="mobile-nav-icon right">
<img class="toggle-icon" src="../../assets/img/hamburger-nav.svg">
</div>
<ul class="main-nav nav-links right flex flex-vert-center flex-space-between">
<li>
<a class="nav-link hide-mobile">Get Started</a>
<ul class="sub-menu bg-white">
<li class="pa-micro">
<a href="/_/cassandra-basics.html">
<div class="sub-nav-icon">
<img src="../../assets/img/sub-menu-basics.png" alt="cassandra basics icon">
</div>
<div class="sub-nav-text teal py-small">
Cassandra Basics
</div>
</a>
</li>
<li class="pa-micro">
<a href="/_/quickstart.html">
<div class="sub-nav-icon">
<img src="../../assets/img/sub-menu-rocket.png" alt="cassandra basics icon">
</div>
<div class="sub-nav-text teal py-small">
Quickstart
</div>
</a>
</li>
<li class="pa-micro">
<a href="/_/ecosystem.html">
<div class="sub-nav-icon">
<img src="../../assets/img/sub-menu-ecosystem.png" alt="cassandra basics icon">
</div>
<div class="sub-nav-text teal py-small">
Ecosystem
</div>
</a>
</li>
</ul>
</li>
<li><a class="nav-link" href="/doc/latest/">Documentation</a></li>
<li>
<a class="nav-link" href="/_/community.html">Community</a>
<ul class="sub-menu bg-white">
<li class="pa-micro">
<a href="/_/community.html#code-of-conduct">
<div class="sub-nav-icon">
<img src="../../assets/img/sub-menu-welcome.png" alt="welcome icon">
</div>
<div class="sub-nav-text teal py-small">
Welcome
</div>
</a>
</li>
<li class="pa-micro hide-mobile">
<a href="/_/community.html#discussions">
<div class="sub-nav-icon">
<img src="../../assets/img/sub-menu-discussions.png" alt="discussions icon">
</div>
<div class="sub-nav-text teal py-small">
Discussions
</div>
</a>
</li>
<li class="pa-micro hide-mobile">
<a href="/_/community.html#project-governance">
<div class="sub-nav-icon">
<img src="../../assets/img/sub-menu-governance.png" alt="Governance icon">
</div>
<div class="sub-nav-text teal py-small">
Governance
</div>
</a>
</li>
<li class="pa-micro hide-mobile">
<a href="/_/community.html#how-to-contribute">
<div class="sub-nav-icon">
<img src="../../assets/img/sub-menu-contribute.png" alt="Contribute icon">
</div>
<div class="sub-nav-text teal py-small">
Contribute
</div>
</a>
</li>
<li class="pa-micro hide-mobile">
<a href="/_/community.html#meet-the-community">
<div class="sub-nav-icon">
<img src="../../assets/img/sub-menu-community.png" alt="Meet the Community icon">
</div>
<div class="sub-nav-text teal py-small">
Meet the Community
</div>
</a>
</li>
<li class="pa-micro hide-mobile">
<a href="/_/cassandra-catalyst-program.html">
<div class="sub-nav-icon">
<img src="../../assets/img/sub-menu-catalyst.png" alt="Catalyst icon">
</div>
<div class="sub-nav-text teal py-small">
Catalyst Program
</div>
</a>
</li>
<li class="pa-micro hide-mobile">
<a href="/_/events.html">
<div class="sub-nav-icon">
<img src="../../assets/img/sub-menu-events.png" alt="Events icon">
</div>
<div class="sub-nav-text teal py-small">
Events
</div>
</a>
</li>
</ul>
</li>
<li>
<a class="nav-link hide-mobile">Learn</a>
<ul class="sub-menu bg-white">
<li class="pa-micro">
<a href="/_/Apache-Cassandra-5.0-Moving-Toward-an-AI-Driven-Future.html">
<div class="sub-nav-icon">
<img src="../../assets/img/sub-menu-basics.png" alt="Basics icon">
</div>
<div class="sub-nav-text teal py-small">
Cassandra 5.0
</div>
</a>
</li>
<li class="pa-micro">
<a href="/_/case-studies.html">
<div class="sub-nav-icon">
<img src="../../assets/img/sub-menu-case-study.png" alt="Case Studies icon">
</div>
<div class="sub-nav-text teal py-small">
Case Studies
</div>
</a>
</li>
<li class="pa-micro">
<a href="/_/resources.html">
<div class="sub-nav-icon">
<img src="../../assets/img/sub-menu-resources.png" alt="Resources icon">
</div>
<div class="sub-nav-text teal py-small">
Resources
</div>
</a>
</li>
<li class="pa-micro">
<a href="/_/blog.html">
<div class="sub-nav-icon">
<img src="../../assets/img/sub-menu-blog.png" alt="Blog icon">
</div>
<div class="sub-nav-text teal py-small">
Blog
</div>
</a>
</li>
</ul>
</li>
<li><a class="nav-link btn btn--filled" href="/_/download.html">Download Now</a></li>
</ul>
</div>
</div>
</header>
<div class="hero hero--home grad">
<div class="eye"></div>
<div id="home-content" class="text-center flex flex-center flex-column relative z2 ma-xlarge">
<h1>Tightening security for Apache Cassandra: Part 3</h1>
<h3>February, 14 2022 | Maulin Vasavada</h3>
</div>
</div>
<div id="blog-post" class="flex-center py-large arrow">
<div class="blog-breadcrumb mb-medium">
<div class="inner inner--narrow">
<a href="/_/blog.html">« Back to the Apache Cassandra Blog</a>
</div>
</div>
<div class="post-content">
<div class="inner inner--narrow">
<div id="preamble">
<div class="sectionbody">
<div class="imageblock">
<div class="content">
<img src="../_images/blog/tightening-security-for-apache-cassandra-p3-unsplash-jennefer-zacarias.jpg" alt="3-4">
</div>
<div class="title">Image credit: <a href="https://unsplash.com/@zenchic" target="_blank" rel="noopener">Jennefer Zacarias</a></div>
</div>
<div class="paragraph">
<p>In <a href="Tightening-Security-for-Apache-Cassandra-Part-2.html" class="page">Part-2</a> of this series, we explored avenues for securing data in transit and described how to configure TLS/mTLS with Apache Cassandra 4.0. In Part 3, we’ll look at how you can customize TLS/mTLS for Apache Cassandra 4.1+ to overcome the challenges with a TLS configuration.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="how-we-made-tls-configuration-better-with-4-1"><a class="anchor" href="#how-we-made-tls-configuration-better-with-4-1"></a>How We Made TLS Configuration Better With 4.1</h3>
<div class="paragraph">
<p>With Apache Cassandra 4.1, <a href="https://cwiki.apache.org/confluence/display/CASSANDRA/CEP-9%3A+Make+SSLContext+creation+pluggable" target="_blank" rel="noopener">we enhanced</a> the TLS/mTLS configuration to allow for specifying custom ways to build SSLContext and we provided a default implementation for backward compatibility. We introduced a new configuration, <code>ssl_context_factory</code>, where you can specify your custom class to build SSLContext objects required by Java/Netty SSL libraries. You can also add custom properties to it via simple key-value pairs. All of this has been achieved while retaining the ability to hot-reload the security credentials as you could before version 4.0.</p>
</div>
<div class="paragraph">
<p>To demonstrate this customization, let’s use the example of Kubernetes, the popular cloud-native solution. Kubernetes allows configuring <a href="https://kubernetes.io/docs/concepts/configuration/secret/" target="_blank" rel="noopener">Secrets</a> to store sensitive data. We could potentially use K8s Secrets to store the keystore and truststore artifacts along with their respective passwords. We will assume Apache Cassandra is already running in a K8s environment.</p>
</div>
</div>
<div class="sect2">
<h3 id="integration-with-kubernetes-secrets"><a class="anchor" href="#integration-with-kubernetes-secrets"></a>Integration with Kubernetes Secrets</h3>
<div class="paragraph">
<p>We have passwords for keystore and truststore as K8s environment variables loaded from the K8s Secrets. The keystore and truststore files are loaded by the K8s Secrets. The YAML file, below, for the pod reflects these settings. This example also keeps the hot-reloading capability of security credentials by allowing the secret named <code>keystore/truststore-last-updatedtime</code>. You can update the timestamp value for those secrets via a <code>kubectl</code> command and the implementation will hot-reload the security credentials as it would filesystem-based security credentials.</p>
</div>
<div class="sect3">
<h4 id="example-k8s-pod-configuration"><a class="anchor" href="#example-k8s-pod-configuration"></a>Example K8s Pod Configuration</h4>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">apiVersion: v1
kind: Pod
metadata:
name: my-cassandra-pod
labels:
app: my-cassandra-app
spec:
containers:
- name: my-cassandra-app
image: my-cassandrda-app:latest
imagePullPolicy: Always
env:
- name: KEYSTORE_PASSWORD
valueFrom:
secretKeyRef:
name: my-ssl-store
key: keystore-password
- name: TRUSTSTORE_PASSWORD
valueFrom:
secretKeyRef:
name: my-ssl-store
key: truststore-password
volumeMounts:
- name: my-ssl-store
mountPath: "/etc/my-ssl-store"
readOnly: true
volumes:
- name: my-ssl-store
secret:
secretName: my-ssl-store
items:
- key: cassandra_ssl_keystore
path: keystore
- key: keystore-last-updatedtime
path: keystore-last-updatedtime
- key: cassandra_ssl_truststore
path: truststore
- key: truststore-last-updatedtime
path: truststore-last-updatedtime</code></pre>
</div>
</div>
<div class="paragraph">
<p>We will use the <a href="https://github.com/apache/cassandra/blob/trunk/examples/ssl-factory/src/org/apache/cassandra/security/KubernetesSecretsSslContextFactory.java" target="_blank" rel="noopener">‘KubernetesSecretsSslContextFactory’</a> class from Apache Cassandra 4.1 as an example for how to customize the TLS configuration via Kubernetes Secrets as loaded by the pod definition (above).</p>
</div>
</div>
<div class="sect3">
<h4 id="example-custom-tls-configuration-for-k8s-secrets"><a class="anchor" href="#example-custom-tls-configuration-for-k8s-secrets"></a>Example Custom TLS Configuration for K8s Secrets</h4>
<div class="paragraph">
<p>Here we have used the configuration for <code>server_encryption_options</code>, but, similarly, you can use it for the <code>client_encryption_options</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc"> server_encryption_options:
internode_encryption: none
ssl_context_factory:
class_name: `org.apache.cassandra.security.KubernetesSecretsSslContextFactory
parameters:
KEYSTORE_PASSWORD_ENV_VAR: KEYSTORE_PASSWORD
KEYSTORE_UPDATED_TIMESTAMP_PATH: /etc/my-ssl-store/keystore-last-updatedtime
TRUSTSTORE_PASSWORD_ENV_VAR: TRUSTSTORE_PASSWORD
TRUSTSTORE_UPDATED_TIMESTAMP_PATH: /etc/my-ssl-store/truststore-last-updatedtime
keystore: /etc/my-ssl-store/keystore
truststore: /etc/my-ssl-store/truststore</code></pre>
</div>
</div>
<div class="paragraph">
<p>And Voila! Congratulations, your Apache Cassandra server is now integrated with the Kubernetes Secrets for the TLS configuration. The example above is built on the extensible class hierarchy shown, below. You can build extensions at three different levels and use composition to offer hybrid solutions you might need.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../_images/blog/Cassandra-SslContextFactory.png" alt="A diagram of Apache Cassandra’s extensible class hierarchy">
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="future-work"><a class="anchor" href="#future-work"></a>Future work</h3>
<div class="paragraph">
<p>On top of having the ability to customize TLS configuration, the community is <a href="https://issues.apache.org/jira/browse/CASSANDRA-17031" target="_blank" rel="noopener">working on</a> supporting other popular formats for security credentials, such as <a href="https://www.ssl.com/guide/pem-der-crt-and-cer-x-509-encodings-and-conversions/" target="_blank" rel="noopener">PEM</a> (originally “<strong>P</strong>rivacy <strong>E</strong>nhanced <strong>M</strong>ail”).</p>
</div>
<div class="paragraph">
<p>As the Apache Cassandra community, our goal is to provide best-in-class software and keep enhancing it as the use-cases and requirements grow and evolve over time. I hope this particular enhancement makes Cassandra operators’ life easier while supporting industry standards for data security.</p>
</div>
<div class="paragraph">
<p><em>Update: The original blog has been updated to correctly reflect Apache Cassandra version 4.1 for the SSL Context&#8217;s customization feature. Apache Cassandra 4.1 changes are targeted to freeze in May 2022 and released in July 2022</em></p>
</div>
</div>
</div>
</div>
</div>
<footer class="grad grad--two flex-center pb-xlarge">
<div class="inner text-center z2 relative">
<h2 class="white py-small">Get started with Cassandra, fast.</h2>
<a id="footer-cta" href="/_/quickstart.html" class="btn btn--filled ma-medium">Quickstart Guide</a>
</div>
<div class="inner flex flex-distribute-items mt-xlarge z2 relative">
<div class="col-2">
<div id="footer-logo" class="logo logo--footer mb-medium"><img src="../../assets/img/logo-white-r.png" alt="Cassandra Logo"></div>
<p>Apache Cassandra<img src="../../assets/img/registered.svg" alt="®" style="width:18px;"> powers mission-critical deployments with improved performance and unparalleled levels of scale in the cloud.</p>
<div class="footer-social-icons">
<a href="https://twitter.com/cassandra?lang=en" target="_blank"><img src="../../assets/img/twitter-icon-circle-white.svg" alt="twitter icon" width="24"></a>
<a href="https://www.linkedin.com/company/apache-cassandra/" target="_blank"><img src="../../assets/img/LI-In-Bug.png" alt="linked-in icon" width="24"></a>
<a href="https://www.youtube.com/c/PlanetCassandra" target="_blank"><img src="../../assets/img/youtube-icon.png" alt="youtube icon" width="24"></a>
</div>
</div>
<div class="col-2 flex flex-center">
<ul class="columns-2">
<li class="mb-small"><a href="/">Home</a></li>
<li class="mb-small"><a href="/_/cassandra-basics.html">Cassandra Basics</a></li>
<li class="mb-small"><a href="/_/quickstart.html">Quickstart</a></li>
<li class="mb-small"><a href="/_/ecosystem.html">Ecosystem</a></li>
<li class="mb-small"><a href="/doc/latest/">Documentation</a></li>
<li class="mb-small"><a href="/_/community.html">Community</a></li>
<li class="mb-small"><a href="/_/case-studies.html">Case Studies</a></li>
<li class="mb-small"><a href="/_/resources.html">Resources</a></li>
<li class="mb-small"><a href="/_/blog.html">Blog</a></li>
</ul>
</div>
</div>
</footer>
<div class="lower-footer bg-white pa-medium">
<div class="flex flex-row flex-vert-center">
<div class="pr-medium"><img src="../../assets/img//feather-small.png" alt="ASF" width="20"></div>
<div class="pr-medium"><a href="http://www.apache.org/" target="_blank">Foundation</a></div>
<div class="pr-medium"><a href="https://www.apache.org/events/current-event.html" target="_blank">Events</a></div>
<div class="pr-medium"><a href="https://www.apache.org/licenses/" target="_blank">License</a></div>
<div class="pr-medium"><a href="https://www.apache.org/foundation/thanks" target="_blank">Thanks</a></div>
<div class="pr-medium"><a href="https://www.apache.org/security" target="_blank">Security</a></div>
<div class="pr-medium"><a href="https://privacy.apache.org/policies/privacy-policy-public.html" target="_blank">Privacy</a></div>
<div class="pr-medium"><a href="https://www.apache.org/foundation/sponsorship" target="_blank">Sponsorship</a></div>
</div>
<p class="my-medium">© 2009-<script>document.write(new Date().getFullYear())</script> <a href="https://apache.org" target="_blank">The Apache Software Foundation</a> under the terms of the Apache License 2.0. Apache, the Apache feather logo, Apache Cassandra, Cassandra, and the Cassandra logo, are either registered trademarks or trademarks of The Apache Software Foundation.</p>
</div>
<div id="fade" class="hidden"></div>
<div id="modal" class="hidden">
<div id="close-modal" class="cursor-pointer"><svg viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round" class="css-i6dzq1"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg></div>
<div id="mod-content" class="vid-mod-content resp-container"></div>
</div>
<script>
jQuery(function(){
var windowW = $(window).width();
$(document)
.on('click','.mobile-nav-icon',function(){
$('.main-nav').fadeIn();
})
.on('click','.main-nav',function(){
if(windowW <= 1000){
$(this).fadeOut();
}
})
.on('click','#version-toggle',function(){
$(this).toggleClass('active');
$(this).next().fadeToggle();
})
.on('click','#mobile-docs-nav-burger', function(){
$(this).toggleClass('active');
$('.docs-nav').toggleClass('active');
});
var url = window.location.pathname;
var isQuickstart = url.includes('quickstart.html');
if(isQuickstart){
var footerCTA = document.getElementById('footer-cta');
footerCTA.innerHTML = 'Get latest updates';
footerCTA.setAttribute('href', '/_/blog.html');
}
});
</script>
</div>
</body>
<script>
jQuery(function(){
});
</script>
</html>