<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://kviklet.dev/blog/</id>
    <title>Kviklet Blog Blog</title>
    <updated>2024-08-05T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://kviklet.dev/blog/"/>
    <subtitle>Kviklet Blog Blog</subtitle>
    <icon>https://kviklet.dev/blog/img/favicon.ico</icon>
    <entry>
        <title type="html"><![CDATA[DevOps and Compliance: Not Enemies, But Allies]]></title>
        <id>https://kviklet.dev/blog/devops-compliance</id>
        <link href="https://kviklet.dev/blog/devops-compliance"/>
        <updated>2024-08-05T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[How to make DevOps work while staying compliant]]></summary>
        <content type="html"><![CDATA[<p><img loading="lazy" alt="DevOps and Compliance" src="https://kviklet.dev/blog/assets/images/compliance_cut-d5cdf90fdce94bb0268fcccb8b34f3af.png" title="DevOps and Compliance" width="1594" height="690" class="img_CujE border_colored_e1LE"></p>
<p>Let's cut straight through the bullshit: if you're an engineer working in a company that deals with sensitive data or operates in a regulated industry, you've probably rolled your eyes at the mention of "compliance" more times than you can count. SOC2, ISO27001, HIPAA, GDPR – these acronyms often feel like speed bumps on the highway of rapid development and deployment.</p>
<p>But here's the kicker: DevOps and compliance aren't natural enemies. In fact, when done right, they're powerful allies that can supercharge your software development process and keep your ass out of regulatory hot water. So buckle up, because we're about to dive into how you can make DevOps and compliance work together without sacrificing your sanity or your velocity.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-compliance-conundrum-in-devops">The Compliance Conundrum in DevOps<a href="https://kviklet.dev/blog/devops-compliance#the-compliance-conundrum-in-devops" class="hash-link" aria-label="Direct link to The Compliance Conundrum in DevOps" title="Direct link to The Compliance Conundrum in DevOps">​</a></h2>
<p>First things first: let's address the elephant in the room. Many engineers view compliance as the antithesis of DevOps practices. DevOps is all about speed, automation, and continuous improvement, right? Meanwhile, compliance feels like a bureaucratic nightmare of checklists, audits, and red tape that is impossible to argue with because someone will just throw a regulatory acronym in your face if you try to.</p>
<p>But here's the truth: The people that developed these frameworks, and regulations didn't do it to annoy engineers and slow them down. They instead have security and the users well-being at heart. And I guarantee that no engineer wants to purposefully builda vulnerable piece of software or leak their users data. So what gives? Somewhere between the ink dropping on those regulatory papers and us building development flows that purpose was somehow lost.</p>
<p>The key to keep the spirit of compliance without slowing down your development is to bake compliance into your DevOps practices from the get-go. This approach, often called "Continuous Compliance" or "DevSecOps," integrates security and compliance checks throughout the entire software development lifecycle. It's not about slowing you down; it's about making sure you have sane practices in place to protect your users and your business. Just like refactoring every now and then to keep your codebase clean and maintainable, compliance, if done right, will make sure your infrastructure and data are safe and secure.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="integrating-compliance-into-your-devops-pipeline">Integrating Compliance into Your DevOps Pipeline<a href="https://kviklet.dev/blog/devops-compliance#integrating-compliance-into-your-devops-pipeline" class="hash-link" aria-label="Direct link to Integrating Compliance into Your DevOps Pipeline" title="Direct link to Integrating Compliance into Your DevOps Pipeline">​</a></h2>
<p>So, how do we actually make this work? Let's break it down:</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="1-version-control-your-compliance-best-friend">1. Version Control: Your Compliance Best Friend<a href="https://kviklet.dev/blog/devops-compliance#1-version-control-your-compliance-best-friend" class="hash-link" aria-label="Direct link to 1. Version Control: Your Compliance Best Friend" title="Direct link to 1. Version Control: Your Compliance Best Friend">​</a></h3>
<p>If you're not using version control, stop reading this article and go set it up right now. Seriously, I'll wait.</p>
<p>Version control isn't just about tracking code changes. It's a compliance goldmine. Every commit is a record of what changed, who changed it, and when. This traceability is music to auditors' ears. Use branching strategies and pull requests to enforce code reviews, which not only improves code quality but also serves as evidence of your change management process.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="2-infrastructure-as-code-iac-compliance-at-scale">2. Infrastructure as Code (IaC): Compliance at Scale<a href="https://kviklet.dev/blog/devops-compliance#2-infrastructure-as-code-iac-compliance-at-scale" class="hash-link" aria-label="Direct link to 2. Infrastructure as Code (IaC): Compliance at Scale" title="Direct link to 2. Infrastructure as Code (IaC): Compliance at Scale">​</a></h3>
<p>Infrastructure as Code isn't just a cool DevOps practice; it's a compliance superhero. By defining your infrastructure in code, you create a single source of truth for your environment configurations. This makes it infinitely easier to demonstrate compliance with security standards and to quickly remediate issues across your entire infrastructure.</p>
<p>Tools like Terraform or AWS CloudFormation don't just make your life easier; they make your compliance team's job a breeze. And trust me, a happy compliance team means fewer headaches for you.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="3-automated-testing-your-first-line-of-defense">3. Automated Testing: Your First Line of Defense<a href="https://kviklet.dev/blog/devops-compliance#3-automated-testing-your-first-line-of-defense" class="hash-link" aria-label="Direct link to 3. Automated Testing: Your First Line of Defense" title="Direct link to 3. Automated Testing: Your First Line of Defense">​</a></h3>
<p>Continuous integration isn't complete without automated testing. But don't stop at unit tests and integration tests. Incorporate security scanning and compliance checks into your CI pipeline. Tools like SonarQube, OWASP Dependency-Check, and custom scripts can catch potential compliance violations before they ever reach production.</p>
<p>Remember: fixing a compliance issue in development is infinitely cheaper and less stressful than explaining to auditors why you have unencrypted PII floating around in prod.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="4-immutable-infrastructure-reduce-your-attack-surface">4. Immutable Infrastructure: Reduce Your Attack Surface<a href="https://kviklet.dev/blog/devops-compliance#4-immutable-infrastructure-reduce-your-attack-surface" class="hash-link" aria-label="Direct link to 4. Immutable Infrastructure: Reduce Your Attack Surface" title="Direct link to 4. Immutable Infrastructure: Reduce Your Attack Surface">​</a></h3>
<p>Embracing immutable infrastructure isn't just a trendy DevOps practice; it's a compliance dream. By treating your servers as disposable and frequently replacing them with fresh, up-to-date images, you reduce your attack surface and make it easier to maintain a known-good state.</p>
<p>This approach aligns perfectly with compliance requirements around patch management and system integrity. Plus, it makes rolling back changes a breeze if something does go wrong.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="5-continuous-monitoring-real-time-compliance">5. Continuous Monitoring: Real-time Compliance<a href="https://kviklet.dev/blog/devops-compliance#5-continuous-monitoring-real-time-compliance" class="hash-link" aria-label="Direct link to 5. Continuous Monitoring: Real-time Compliance" title="Direct link to 5. Continuous Monitoring: Real-time Compliance">​</a></h3>
<p>DevOps teams love their monitoring tools, and guess what? So do compliance folks. Implement robust logging and monitoring across your entire stack. This isn't just about catching performance issues; it's about having real-time visibility into your compliance posture.</p>
<p>Tools like ELK stack (Elasticsearch, Logstash, Kibana) or cloud-native solutions like AWS CloudWatch can be configured to alert on potential compliance violations, from unauthorized access attempts to unusual data access patterns.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="6-automated-documentation-because-no-one-likes-writing-docs">6. Automated Documentation: Because No One Likes Writing Docs<a href="https://kviklet.dev/blog/devops-compliance#6-automated-documentation-because-no-one-likes-writing-docs" class="hash-link" aria-label="Direct link to 6. Automated Documentation: Because No One Likes Writing Docs" title="Direct link to 6. Automated Documentation: Because No One Likes Writing Docs">​</a></h3>
<p>Let's face it: documentation is often the bane of a developer's existence. But it's also crucial for compliance. The solution? Automate it as much as possible.</p>
<p>Use tools that can generate documentation from your code, infrastructure definitions, and CI/CD pipelines. Swagger for API documentation, automated changelog generation, and even AI-powered documentation tools can significantly reduce the manual effort while keeping your docs up-to-date.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="7-access-control-and-secrets-management-lock-it-down">7. Access Control and Secrets Management: Lock It Down<a href="https://kviklet.dev/blog/devops-compliance#7-access-control-and-secrets-management-lock-it-down" class="hash-link" aria-label="Direct link to 7. Access Control and Secrets Management: Lock It Down" title="Direct link to 7. Access Control and Secrets Management: Lock It Down">​</a></h3>
<p>Proper access control is a cornerstone of compliance, but it doesn't have to be a pain in the ass. Implement robust identity and access management (IAM) practices across your entire stack. Use tools like HashiCorp Vault or AWS Secrets Manager to securely store and manage secrets.</p>
<p>And for the love of all that is holy, stop hardcoding credentials in your code or config files. It's 2024, and there's no excuse for that nonsense.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-human-element-building-a-compliance-aware-culture">The Human Element: Building a Compliance-Aware Culture<a href="https://kviklet.dev/blog/devops-compliance#the-human-element-building-a-compliance-aware-culture" class="hash-link" aria-label="Direct link to The Human Element: Building a Compliance-Aware Culture" title="Direct link to The Human Element: Building a Compliance-Aware Culture">​</a></h2>
<p>All the tools and automation in the world won't save you if your team doesn't buy into the importance of compliance. Here's how to build a compliance-aware culture without turning into the fun police:</p>
<ol>
<li>
<p><strong>Education is Key</strong>: Don't just tell your team to "be compliant." Explain why certain practices are important and how they protect the business (and their jobs).</p>
</li>
<li>
<p><strong>Make it Easy</strong>: Provide clear guidelines, templates, and tools that make following compliance requirements as painless as possible.</p>
</li>
<li>
<p><strong>Celebrate Compliance Wins</strong>: Did someone catch a potential compliance issue early? Give them a shout-out. Make compliance a source of pride, not just a box to tick.</p>
</li>
<li>
<p><strong>Empower Your Team</strong>: Give developers the tools and authority to address compliance issues themselves, rather than relying on a separate compliance team for every little thing.</p>
</li>
<li>
<p><strong>Continuous Improvement</strong>: Regularly review and update your compliance processes. If something's not working or is causing unnecessary friction, fix it.</p>
</li>
</ol>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="tools-of-the-trade-making-compliance-suck-less">Tools of the Trade: Making Compliance Suck Less<a href="https://kviklet.dev/blog/devops-compliance#tools-of-the-trade-making-compliance-suck-less" class="hash-link" aria-label="Direct link to Tools of the Trade: Making Compliance Suck Less" title="Direct link to Tools of the Trade: Making Compliance Suck Less">​</a></h2>
<p>Alright, let's talk tools. There's a whole ecosystem of solutions out there designed to make DevOps compliance less of a headache. Here are a few worth checking out:</p>
<ol>
<li>
<p><strong>Chef InSpec</strong>: An open-source framework for testing and auditing your applications and infrastructure.</p>
</li>
<li>
<p><strong>Prisma Cloud (formerly Twistlock)</strong>: Provides full-stack security and compliance management for cloud-native applications.</p>
</li>
<li>
<p><strong>Anchore</strong>: Analyzes container images for vulnerabilities and policy violations.</p>
</li>
<li>
<p><strong>Compliance as Code tools</strong>: Solutions like AWS Config Rules or Azure Policy that let you define and enforce compliance rules programmatically.</p>
</li>
<li>
<p><strong>Kviklet</strong>: Yeah, I'm gonna plug my own tool here. Kviklet helps you manage secure access to production environments without killing developer productivity. It's perfect for teams that need to maintain compliance while still giving devs the access they need to get shit done.</p>
</li>
</ol>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-bottom-line-compliance-doesnt-have-to-suck">The Bottom Line: Compliance Doesn't Have to Suck<a href="https://kviklet.dev/blog/devops-compliance#the-bottom-line-compliance-doesnt-have-to-suck" class="hash-link" aria-label="Direct link to The Bottom Line: Compliance Doesn't Have to Suck" title="Direct link to The Bottom Line: Compliance Doesn't Have to Suck">​</a></h2>
<p>Here's the deal: compliance isn't going away. If anything, regulatory requirements are only going to get stricter as data privacy concerns grow and cyber threats evolve. But that doesn't mean we have to choose between being compliant and being agile.</p>
<p>By integrating compliance into your DevOps practices, you're not just checking boxes for auditors. You're building more robust, secure systems. You're reducing the risk of costly data breaches or compliance violations. And most importantly, you're setting up your team for sustainable, long-term success.</p>
<p>Remember, the goal isn't to be compliant for compliance's sake. It's about building trust with your customers, protecting your business, and yes, covering your ass legally. But when done right, it also leads to better software, more efficient processes, and a team that can sleep soundly at night knowing they're not one misconfigured S3 bucket away from a data breach nightmare.</p>
<p>So stop treating compliance like a necessary evil and start seeing it as an integral part of your software development lifecycle. Embrace the tools and practices that make continuous compliance possible. And for fuck's sake, if you're still managing production access with shared SSH keys shared read only accounts to the database,it's truly time to grow up and get serious about security.</p>
<p>DevOps and compliance can be allies, not enemies. It's time we started treating them that way.</p>
<hr>
<p>Got thoughts on DevOps and compliance? Struggling to make it work in your organization? Feel free to reach out on Threads or LinkedIn. And if you're looking for a tool to help manage secure access to your production environments without sacrificing developer productivity, check out <a href="https://kviklet.dev/" target="_blank" rel="noopener noreferrer">Kviklet</a>. It might just be the missing piece in your DevOps compliance puzzle.</p>]]></content>
        <author>
            <name>Jascha Beste</name>
            <uri>https://www.linkedin.com/in/jaschabeste/</uri>
        </author>
        <category label="Production Access" term="Production Access"/>
        <category label="DevOps" term="DevOps"/>
        <category label="DevSecOps" term="DevSecOps"/>
        <category label="Compliance" term="Compliance"/>
        <category label="SOC 2" term="SOC 2"/>
        <category label="GDPR" term="GDPR"/>
        <category label="ISO27001" term="ISO27001"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[New Vulnerability in OpenSSH Shakes Up the DevOps World]]></title>
        <id>https://kviklet.dev/blog/openssh-remote-access-vulnerability</id>
        <link href="https://kviklet.dev/blog/openssh-remote-access-vulnerability"/>
        <updated>2024-07-02T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[80% of Companies Running Cloud Inra at Risk and 14 Million OpenSSH Servers Vulnerable]]></summary>
        <content type="html"><![CDATA[<p>On June 30, 2024, Qualys, a US security firm, has discovered a critical vulnerability in OpenSSH Server - the de facto standard tool used to access and manage cloud servers.<a href="https://blog.qualys.com/vulnerabilities-threat-research/2024/07/01/regresshion-remote-unauthenticated-code-execution-vulnerability-in-openssh-server" target="_blank" rel="noopener noreferrer">[1]</a></p>
<p>The vulnerability allows an attacker to bypass the authentication process and remotely execute code with root-level access on the system, potentially leading to data theft or system compromise. At risk are OpenSSH versions 8.5p1 (2020) to 9.7p1 (2024) or below 4.4p1 (2006).</p>
<p>The "Remote Code Execution" (RCE) vulnerability has been assigned CVE-2024-6387 and dubbed "regreSSHion" - This is pun to this being a regression bug because it has been reported and fixed in 2006 (CVE-2006-5051) and reintroduced in 2020.</p>
<p>Luckily the vulnerability is (still) challenging to exploit, requiring multiple attempts and timing for a succesful attack - but any serious organization would want to mitigate this risk immediately.<br>
<!-- -->For the real Geeks among us - A basic proof of concept exploit has been published on GitHub. <a href="https://github.com/zgzhang/cve-2024-6387-poc" target="_blank" rel="noopener noreferrer">[2]</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="80-of-companies-with-cloud-using-openssh">80% of Companies with Cloud using OpenSSH<a href="https://kviklet.dev/blog/openssh-remote-access-vulnerability#80-of-companies-with-cloud-using-openssh" class="hash-link" aria-label="Direct link to 80% of Companies with Cloud using OpenSSH" title="Direct link to 80% of Companies with Cloud using OpenSSH">​</a></h2>
<p>OpenSSH has become the de facto standard for remote access to servers. It is used by DevOps, SysAdmins, Engineers, and Security teams to manage (cloud) infrastructure, and is often the first tool to be installed on a new server.</p>
<p>WIZ, a cloud security company, estimates that 80% of organizations with cloud environments have at least one vulnerable instance of OpenSSH running, putting them at risk.&nbsp;<a href="https://www.wiz.io/blog/cve-2024-6387-critical-rce-openssh" target="_blank" rel="noopener noreferrer">[3]</a></p>
<p>Qualys has run internet scans and identified 14 million potentially vulnerable OpenSSH servers, which are accessible from the internet(!). <a href="https://blog.qualys.com/vulnerabilities-threat-research/2024/07/01/regresshion-remote-unauthenticated-code-execution-vulnerability-in-openssh-server" target="_blank" rel="noopener noreferrer">[1]</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="mitigation-1-update-openssh---or-change-config-and-risk-dos">Mitigation 1: Update OpenSSH - or Change Config and Risk DOS<a href="https://kviklet.dev/blog/openssh-remote-access-vulnerability#mitigation-1-update-openssh---or-change-config-and-risk-dos" class="hash-link" aria-label="Direct link to Mitigation 1: Update OpenSSH - or Change Config and Risk DOS" title="Direct link to Mitigation 1: Update OpenSSH - or Change Config and Risk DOS">​</a></h2>
<p>Quickly apply patches and update OpenSSH to version 9.8p1, released on July 1st 2024. <a href="https://www.openssh.com/releasenotes.html" target="_blank" rel="noopener noreferrer">[4]</a></p>
<p>If you are unable to update, you can mitigate this vulnerability by changing sshd setting "LoginGraceTime" to "0" in the configuration file. This will eliminate the risk of remote code excution through this vulnerability, but it can make the server susceptible to Denial of Service (DOS) attacks - which is probably a lesser evil than the risk of a remote code execution.</p>
<p><img loading="lazy" alt="Screenshot from X showing a meme, RCE vs. DOS vulnerability" src="https://kviklet.dev/blog/assets/images/X_RCE-or-DOS-39ee9da629ef969b25a4473a6ec32d7d.png" title="Nasreddine Bencherchali, a Security Researcher on X explaining how to mitigate the RCE risk, and instead be susceptiple to DOS attacks." width="960" height="1780" class="img_CujE border_colored_e1LE">
<em>Nasreddine Bencherchali, a Security Researcher on X explaining how to mitigate the RCE risk, and instead be susceptiple to DOS attacks. <a href="https://x.com/nas_bench/status/1807821951433416877" target="_blank" rel="noopener noreferrer">[5]</a></em></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="mitigation-2-use-fail2ban-to-mitigate-both-cve-2024-6387-and-dos-attacks">Mitigation 2: Use Fail2Ban to Mitigate Both CVE-2024-6387 and DOS Attacks<a href="https://kviklet.dev/blog/openssh-remote-access-vulnerability#mitigation-2-use-fail2ban-to-mitigate-both-cve-2024-6387-and-dos-attacks" class="hash-link" aria-label="Direct link to Mitigation 2: Use Fail2Ban to Mitigate Both CVE-2024-6387 and DOS Attacks" title="Direct link to Mitigation 2: Use Fail2Ban to Mitigate Both CVE-2024-6387 and DOS Attacks">​</a></h2>
<p>In order to mitigate against both risks - the RCE and DOS - you can use Fail2Ban, an open-source intrusion prevention software that comes with a default config file for sshd and can automatically alter firewall configuration to ban IPs after a certain number of unsuccessful login attempts. <a href="https://www.digitalocean.com/community/tutorials/how-to-protect-ssh-with-fail2ban-on-ubuntu-20-04" target="_blank" rel="noopener noreferrer">[6]</a><a href="https://x.com/cyb3rops/status/1808089314707784167?s=48&amp;t=tyFllwqVrpzw2rL-cc8b5w" target="_blank" rel="noopener noreferrer">[6]</a></p>
<p><img loading="lazy" alt="Screenshot from X - Florian Roth on Fail2Ban to mitigate the risks " src="https://kviklet.dev/blog/assets/images/X_Fail2Ban_FlorianRoth-7c77d87ef40efb42755a1f9957d3ad35.png" title="Florian Roth, a Security Researcher on X explaining how to mitigate both RCE and DOS risk using Fail2Ban." width="1180" height="906" class="img_CujE border_colored_e1LE">
<em>Florian Roth, a Security Researcher on X explaining how to mitigate both RCE and DOS risk using Fail2Ban. <a href="https://x.com/cyb3rops/status/1808089314707784167?s=48&amp;t=tyFllwqVrpzw2rL-cc8b5w" target="_blank" rel="noopener noreferrer">[7]</a></em></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="mitigation-3-use-vpn-to-prevent-access-to-ssh-port-22-from-the-internet">Mitigation 3: Use VPN to Prevent Access to SSH Port 22 from the Internet<a href="https://kviklet.dev/blog/openssh-remote-access-vulnerability#mitigation-3-use-vpn-to-prevent-access-to-ssh-port-22-from-the-internet" class="hash-link" aria-label="Direct link to Mitigation 3: Use VPN to Prevent Access to SSH Port 22 from the Internet" title="Direct link to Mitigation 3: Use VPN to Prevent Access to SSH Port 22 from the Internet">​</a></h2>
<p>Use a VPN such as WireGuard or the open-source Netbird in front of the SSH service. This will prevent attackers from accessing the SSH port 22 from the internet, reducing the risk of remote exploitation. <a href="https://www.digitalocean.com/community/tutorials/how-to-protect-ssh-with-fail2ban-on-ubuntu-20-04" target="_blank" rel="noopener noreferrer">[6]</a><a href="https://netbird.io/knowledge-hub/using-ssh-to-secure-remote-access" target="_blank" rel="noopener noreferrer">[8]</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-to-identify-exploitation-attempts-and-systems-at-risk">How to Identify Exploitation Attempts and Systems at Risk<a href="https://kviklet.dev/blog/openssh-remote-access-vulnerability#how-to-identify-exploitation-attempts-and-systems-at-risk" class="hash-link" aria-label="Direct link to How to Identify Exploitation Attempts and Systems at Risk" title="Direct link to How to Identify Exploitation Attempts and Systems at Risk">​</a></h2>
<p>To reveal exploitation attempts, set up your monitoring systems to detect multiple occurences of "Timeout before authentication" in the sshd server logfiles. <a href="https://blog.qualys.com/vulnerabilities-threat-research/2024/07/01/regresshion-remote-unauthenticated-code-execution-vulnerability-in-openssh-server" target="_blank" rel="noopener noreferrer">[1]</a></p>
<p>To identify systems at risk, scan your environment for installations of vulnerable versions of the OpenSSH servers.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="references">References<a href="https://kviklet.dev/blog/openssh-remote-access-vulnerability#references" class="hash-link" aria-label="Direct link to References" title="Direct link to References">​</a></h3>
<ol>
<li><a href="https://blog.qualys.com/vulnerabilities-threat-research/2024/07/01/regresshion-remote-unauthenticated-code-execution-vulnerability-in-openssh-server" target="_blank" rel="noopener noreferrer">https://blog.qualys.com/vulnerabilities-threat-research/2024/07/01/regresshion-remote-unauthenticated-code-execution-vulnerability-in-openssh-server</a></li>
<li><a href="https://github.com/zgzhang/cve-2024-6387-poc" target="_blank" rel="noopener noreferrer">https://github.com/zgzhang/cve-2024-6387-poc</a></li>
<li><a href="https://www.wiz.io/blog/cve-2024-6387-critical-rce-openssh" target="_blank" rel="noopener noreferrer">https://www.wiz.io/blog/cve-2024-6387-critical-rce-openssh</a></li>
<li><a href="https://www.openssh.com/releasenotes.html" target="_blank" rel="noopener noreferrer">https://www.openssh.com/releasenotes.html</a></li>
<li><a href="https://x.com/nas_bench/status/1807821951433416877" target="_blank" rel="noopener noreferrer">https://x.com/nas_bench/status/1807821951433416877</a></li>
<li><a href="https://www.digitalocean.com/community/tutorials/how-to-protect-ssh-with-fail2ban-on-ubuntu-20-04" target="_blank" rel="noopener noreferrer">https://www.digitalocean.com/community/tutorials/how-to-protect-ssh-with-fail2ban-on-ubuntu-20-04</a></li>
<li><a href="https://x.com/cyb3rops/status/1808089314707784167?s=48&amp;t=tyFllwqVrpzw2rL-cc8b5w" target="_blank" rel="noopener noreferrer">https://x.com/cyb3rops/status/1808089314707784167?s=48&amp;t=tyFllwqVrpzw2rL-cc8b5w</a></li>
<li><a href="https://netbird.io/knowledge-hub/using-ssh-to-secure-remote-access" target="_blank" rel="noopener noreferrer">https://netbird.io/knowledge-hub/using-ssh-to-secure-remote-access</a></li>
</ol>]]></content>
        <author>
            <name>Dan Nguyen</name>
            <uri>https://www.linkedin.com/in/dan-nguyen-ai/</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Kviklet 0.4 Release Notes]]></title>
        <id>https://kviklet.dev/blog/04-release-notes</id>
        <link href="https://kviklet.dev/blog/04-release-notes"/>
        <updated>2024-06-17T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Kviklet 0.4 is out! We prepared Kviklet to be used by larger teams and polished a bunch of the UX. Check out these release notes to learn more.]]></summary>
        <content type="html"><![CDATA[<p>Kviklet 0.4 is out!
This release includes numerous refinements, which will continue into version 0.5, as Kviklet transitions from a basic MVP to a polished, robust tool that I hope everyone will love to use.
For this release the main focus was to make Kviklet work for teams with a larger member count (think 10+).
The highlights are:</p>
<ul>
<li><strong>New Role and Connection Edit pages</strong>, check them out, should be a lot more intuitive than before.</li>
<li>A <strong>download as CSV button</strong> for Select queries. So that you can use your favorite Spreadsheet tool to analyze and browse the data. Or process it further with your favorite programming language.</li>
<li><strong>Notifications</strong> with error messages if stuff goes wrong (hopefully you dont see them so often). But using Kviklet should have come a lot more intuitive due to this. </li>
<li>Generic <strong>OIDC provider</strong> support (although I still haven't tested all OIDC providers of course). So you can use gitlab, okta, or whatever you want to authenticate your users.</li>
<li><strong>Slack and Teams Notifications</strong> for new Requests and Reviews, so you don't have to ping your teammates manually anymore!</li>
<li>Support for <strong>role-based access-control to specific connections</strong>. You can now use AntMatchers to select a subset of your connections and allow specific roles to create requests on them. This is mainly useful if you have multiple teams using the same Kviklet instance.</li>
<li>A <strong>new default role with readonly permissions</strong>, so that logging in as a new user doesn't look so empty! You can also edit the permissions of this default role.</li>
</ul>
<p>If you have wishes for the next release, feel free to open an issue on <a href="https://github.com/kviklet/kviklet" target="_blank" rel="noopener noreferrer">Github</a> or reach out to me directly.
Progress for 0.5 is tracked in <a href="https://github.com/kviklet/kviklet/issues/138" target="_blank" rel="noopener noreferrer">this issue</a>.</p>]]></content>
        <author>
            <name>Jascha Beste</name>
            <uri>https://www.linkedin.com/in/jaschabeste/</uri>
        </author>
        <category label="ReleaseNotes" term="ReleaseNotes"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Read-Only Database Access for Developers with Audit Logs and SSO]]></title>
        <id>https://kviklet.dev/blog/how-to-readonly-access</id>
        <link href="https://kviklet.dev/blog/how-to-readonly-access"/>
        <updated>2024-05-31T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Learn how to set up secure read-only access for developers with comprehensive audit logging using Kviklet. This guide covers deploying Kviklet, configuring database connections, setting up roles and permissions, enabling SSO, and implementing audit logs. You do not need temporary credentials]]></summary>
        <content type="html"><![CDATA[<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-to-setup-read-only-access-for-developers-with-audit-logs">How to Setup Read-Only Access for Developers with Audit Logs<a href="https://kviklet.dev/blog/how-to-readonly-access#how-to-setup-read-only-access-for-developers-with-audit-logs" class="hash-link" aria-label="Direct link to How to Setup Read-Only Access for Developers with Audit Logs" title="Direct link to How to Setup Read-Only Access for Developers with Audit Logs">​</a></h3>
<p>In today's fast-paced DevOps environment, ensuring that developers have secure yet efficient access to production data is critical. We have written multiple posts on why exactly this is the case, see <a href="https://kviklet.dev/blog/should-engineers-have-production-access/" target="_blank" rel="noopener noreferrer">here</a> and <a href="https://kviklet.dev/blog/devops-production-database-access-guide/" target="_blank" rel="noopener noreferrer">here</a>.
Read-only access to production databases is often a good sweetspot to start with for troubleshooting, analytics, and various operational tasks, that in our experience solves 50%+ of all dev access requests. However, this access must be carefully managed to prevent security risks and maintain compliance. In this guide, we'll walk through how to set up read-only access for developers with comprehensive audit logging using Kviklet, so that your SOC2 or ISO 27001 auditor will be happy.</p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="why-read-only-access">Why Read-Only Access?<a href="https://kviklet.dev/blog/how-to-readonly-access#why-read-only-access" class="hash-link" aria-label="Direct link to Why Read-Only Access?" title="Direct link to Why Read-Only Access?">​</a></h4>
<p>Read-only access allows developers to:</p>
<ul>
<li><strong>Troubleshoot issues</strong>: Quickly identify and resolve bugs by examining live data.</li>
<li><strong>Generate reports</strong>: Access production data for ad-hoc reporting without compromising data integrity. Of course ideally you have a working BI setup for this, but as explained in a previous blog sometimes this is just not sufficient (yet).</li>
<li><strong>Feature Development</strong>: Understand the data model and relationships to develop new features effectively. Typical questions are: Is this column nullable? What is the data type of this column? What is the distribution of this column?</li>
</ul>
<p>However, without proper controls, this can lead to security risks, data breaches, or accidental data manipulation. This is where audit logs and access control come into play.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="setting-up-read-only-access-with-kviklet">Setting Up Read-Only Access with Kviklet<a href="https://kviklet.dev/blog/how-to-readonly-access#setting-up-read-only-access-with-kviklet" class="hash-link" aria-label="Direct link to Setting Up Read-Only Access with Kviklet" title="Direct link to Setting Up Read-Only Access with Kviklet">​</a></h3>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="step-1-deploy-kviklet">Step 1: Deploy Kviklet<a href="https://kviklet.dev/blog/how-to-readonly-access#step-1-deploy-kviklet" class="hash-link" aria-label="Direct link to Step 1: Deploy Kviklet" title="Direct link to Step 1: Deploy Kviklet">​</a></h4>
<p>First, deploy Kviklet as a Docker container. Feel free to go to our repository and copy the docker-compose setup. Otherwise here's a quick setup guide:</p>
<ol>
<li>
<p><strong>Prepare the Database</strong>: Kviklet needs its own database to store metadata about queries, connections, and approvals. Although you can use MySQL, Postgres is recommended. You can find the official image here:
<a href="https://hub.docker.com/_/postgres" target="_blank" rel="noopener noreferrer">https://hub.docker.com/_/postgres</a>.</p>
</li>
<li>
<p><strong>Start the Docker Container</strong>:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">docker run \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">-e SPRING_DATASOURCE_PASSWORD=postgres \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">-e SPRING_DATASOURCE_USERNAME=postgres \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">-e SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5432/kviklet \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">-e INITIAL_USER_EMAIL=admin@example.com \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">-e INITIAL_USER_PASSWORD=someverysecurepassword \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">--network host \ # Use host network for simplicity otherwise kviklet just uses port 80, which you can also expose instead.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">ghcr.io/kviklet/kviklet:main</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>If you see <code>Tomcat started on port(s): 8080 (http)</code> in the logs, Kviklet is up and running. Don't be confused by the port though, There is an nginx proxy that makes sure Kviklet is accessible on port 80.</p>
</li>
</ol>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="step-2-create-a-read-only-user-on-the-database">Step 2: Create a read-only user on the database<a href="https://kviklet.dev/blog/how-to-readonly-access#step-2-create-a-read-only-user-on-the-database" class="hash-link" aria-label="Direct link to Step 2: Create a read-only user on the database" title="Direct link to Step 2: Create a read-only user on the database">​</a></h4>
<p>Kviklet needs a read-only user to access the database. This user should have the necessary permissions to execute read-only queries. Here's how you can create a read-only user in Postgres:</p>
<div class="language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">CREATE</span><span class="token plain"> ROLE readonly_user </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">WITH</span><span class="token plain"> LOGIN PASSWORD </span><span class="token string" style="color:rgb(255, 121, 198)">'password'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">GRANT</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">CONNECT</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">ON</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">DATABASE</span><span class="token plain"> your_database </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">TO</span><span class="token plain"> readonly_user</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">GRANT</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">USAGE</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">ON</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">SCHEMA</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">TO</span><span class="token plain"> readonly_user</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">GRANT</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">SELECT</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">ON</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">ALL</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">TABLES</span><span class="token plain"> </span><span class="token operator">IN</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">SCHEMA</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">TO</span><span class="token plain"> readonly_user</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">ALTER</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">DEFAULT</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">PRIVILEGES</span><span class="token plain"> </span><span class="token operator">IN</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">SCHEMA</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">GRANT</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">SELECT</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">ON</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">TABLES</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">TO</span><span class="token plain"> readonly_user</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>If you have specific tables that the user should not have access to, you can also revoke the SELECT permission on those tables.
If you use MYSQL or Microsoft SQL Server you might want to ask your favorite AI agent for help or look it up in teh documentation of your database.</p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="step-2-configure-database-connections">Step 2: Configure Database Connections<a href="https://kviklet.dev/blog/how-to-readonly-access#step-2-configure-database-connections" class="hash-link" aria-label="Direct link to Step 2: Configure Database Connections" title="Direct link to Step 2: Configure Database Connections">​</a></h4>
<p>After deploying Kviklet, log in to the web interface at <code>http://localhost</code> and configure your database connections:</p>
<ol>
<li>Navigate to <strong>Settings -&gt; Databases -&gt; Add Connection</strong>.</li>
<li>Fill in the connection details for your production database. (username, password, host, port etc.)</li>
<li>Configure the number of reviews required for running requests. If you simply want to provide every engineer with read-only access, you should set this to 0.</li>
</ol>
<p><img loading="lazy" alt="Connection Creation" src="https://kviklet.dev/blog/assets/images/ConnectionCreation-ff4c04814b86f7fa59b72cce9d52f8e0.png" title="The filled out Connection Creation Form" width="1146" height="1418" class="img_CujE border_colored_e1LE"></p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="step-3-set-up-roles-and-permissions">Step 3: Set Up Roles and Permissions<a href="https://kviklet.dev/blog/how-to-readonly-access#step-3-set-up-roles-and-permissions" class="hash-link" aria-label="Direct link to Step 3: Set Up Roles and Permissions" title="Direct link to Step 3: Set Up Roles and Permissions">​</a></h4>
<p>The default Developer Role allows developers to access any connection and create Requests. If you do not have any other connections set up yet, this is perfectly sufficient for read-only access. However, if you want to restrict access further, and add more connections (read separate database users) you might want to edit the developer role or create a separate readonly Role taht only has access to your new readonly connection.</p>
<ol>
<li><strong>Create a Read-Only Role</strong>:<!-- -->
<ul>
<li>Go to <strong>Settings -&gt; Roles -&gt; Create Role</strong>.</li>
<li>Define the permissions for this role, by choosing the ID of you new readonly connection you restrict the access of any user with this role to this specific connection.</li>
</ul>
</li>
<li><strong>Assign the Role to Users</strong>:<!-- -->
<ul>
<li>Navigate to <strong>Settings -&gt; Users</strong>.</li>
<li>Assign the read-only role to the relevant users.</li>
</ul>
</li>
</ol>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="step-4-implement-sso-for-authentication">Step 4: Implement SSO for Authentication<a href="https://kviklet.dev/blog/how-to-readonly-access#step-4-implement-sso-for-authentication" class="hash-link" aria-label="Direct link to Step 4: Implement SSO for Authentication" title="Direct link to Step 4: Implement SSO for Authentication">​</a></h4>
<p>Unless you want to create users for your developers manually and create passwords for each one, you should enable Single Sign-On (SSO) to streamline authentication and enhance security:</p>
<ol>
<li><strong>Google SSO Setup</strong>:<!-- -->
<ul>
<li>Obtain your Google client ID and secret by following <a href="https://developers.google.com/identity/gsi/web/guides/get-google-api-clientid" target="_blank" rel="noopener noreferrer">Google's instructions</a>.</li>
<li>Configure valid redirect URIs: <code>http://[kviklet_host]/api/login/oauth2/code/google</code> in google.</li>
<li>Set the following environment variables in your Kviklet container:<!-- -->
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">KVIKLET_IDENTITY_PROVIDER_CLIENT_ID=your-client-id</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">KVIKLET_IDENTITY_PROVIDER_CLIENT_SECRET=your-client-secret</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">KVIKLET_IDENTITY_PROVIDER_TYPE=google</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
</li>
</ul>
</li>
<li><strong>Or Keycloak SSO Setup</strong>:<!-- -->
<ul>
<li>Set up a client in Keycloak and obtain the client ID and secret.</li>
<li>Set the following environment variables:<!-- -->
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">KVIKLET_IDENTITY_PROVIDER_CLIENT_ID=your-client-id</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">KVIKLET_IDENTITY_PROVIDER_CLIENT_SECRET=your-client-secret</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">KVIKLET_IDENTITY_PROVIDER_TYPE=keycloak</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">KVIKLET_IDENTITY_PROVIDER_ISSUER_URI=http://[host]:[port]/realms/[realm]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
</li>
</ul>
</li>
<li><strong>Assign Roles After Login</strong>:<!-- -->
<ul>
<li>After users log in via SSO, assign them the appropriate role in Kviklet. Alternatively you can simply edit the default role to give access to your new connection. Then you no longer have to do anything manually.</li>
</ul>
</li>
</ol>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="step-5-enable-audit-logging">Step 5: Enable Audit Logging<a href="https://kviklet.dev/blog/how-to-readonly-access#step-5-enable-audit-logging" class="hash-link" aria-label="Direct link to Step 5: Enable Audit Logging" title="Direct link to Step 5: Enable Audit Logging">​</a></h4>
<p>Kviklet automatically logs all database interactions, providing comprehensive audit trails:</p>
<ol>
<li><strong>View Audit Logs</strong>:<!-- -->
<ul>
<li>Navigate to <strong>Audit Logs</strong> in the Kviklet interface.</li>
<li>Review all executed queries, including who executed them and the reasons provided.</li>
</ul>
</li>
</ol>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="step-6-test-the-setup">Step 6: Test the Setup<a href="https://kviklet.dev/blog/how-to-readonly-access#step-6-test-the-setup" class="hash-link" aria-label="Direct link to Step 6: Test the Setup" title="Direct link to Step 6: Test the Setup">​</a></h4>
<p>Before rolling out to the entire team, thoroughly test the setup:</p>
<ol>
<li><strong>Create Test Users</strong>: Assign them the read-only role.</li>
<li><strong>Run Queries</strong>: Have them perform various read-only queries.</li>
<li><strong>Review Audit Logs</strong>: Verify that all queries are logged correctly.</li>
<li>Congrats you now have a self service setup for your developers to access the production database in a secure and compliant way.</li>
</ol>
<p><img loading="lazy" alt="Readonly Example" src="https://kviklet.dev/blog/assets/images/ReadonlyExample-face46fd6bc32da45d7c9369f2425b55.png" title="An example Request" width="1786" height="1282" class="img_CujE border_colored_e1LE"></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="https://kviklet.dev/blog/how-to-readonly-access#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion">​</a></h3>
<p>By following these steps, you can set up secure read-only access for your developers while maintaining comprehensive audit logs. This approach not only enhances security and compliance but also empowers your developers to work more efficiently.</p>
<p>Ready to get started? Deploy <a href="https://kviklet.dev/" target="_blank" rel="noopener noreferrer">Kviklet</a> today and take control of your production database access. For more detailed instructions and community support, visit our <a href="https://github.com/kviklet/kviklet" target="_blank" rel="noopener noreferrer">GitHub repository</a>. If something doesn't work, or you're stuck somewhere or you want a new feature, don't hesitate to open an issue or reach out to us directly. We're here to help you out.</p>]]></content>
        <author>
            <name>Jascha Beste</name>
            <uri>https://www.linkedin.com/in/jaschabeste/</uri>
        </author>
        <category label="DevOps" term="DevOps"/>
        <category label="Security" term="Security"/>
        <category label="Database" term="Database"/>
        <category label="Audit" term="Audit"/>
        <category label="Access Control" term="Access Control"/>
        <category label="SSO" term="SSO"/>
        <category label="Kviklet" term="Kviklet"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Kviklet 0.3 Release Notes]]></title>
        <id>https://kviklet.dev/blog/03-release-notes</id>
        <link href="https://kviklet.dev/blog/03-release-notes"/>
        <updated>2024-05-05T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Kviklet 0.3 is out! We've added a bunch of new features and improvements to make your production access even more secure and efficient. Check out these release notes to learn more.]]></summary>
        <content type="html"><![CDATA[<p>Kviklet 0.3 is out! We've added a bunch of new features and improvements to make your production access even more secure and efficient.
The new release contains a bunch of new features most notably:</p>
<ul>
<li><strong>An integration with Kubernetes Exec,</strong> you can now run commands on other pods after they've been approved through kviklet. The idea behind this is that you can audit your script executions through Kviklet as well as database acces. If this works well we will expand on this further with e.g. a web based console some time?</li>
<li><strong>Support for MS SQL Server Databases</strong>. A wish by the community, if you have other databases that you'd like us to support don't hesitate to open an issue! </li>
<li><strong>The connection settings have gotten an overhaul</strong> so you can now edit all details of a connection after you've created it (except the id)</li>
<li><strong>Requests with multiple results</strong> will now be shown in a paginated matter. So you can put all your selects in a single Request (Or mix in updates and deletes if you really want to).</li>
<li>After running a statement <strong>the audit entry will now contain</strong> a little bit of <strong>metadata</strong> for what happened (rows affected/returned), so not everything is gone if you close the tab.</li>
<li><strong>Configurable max executions per connection</strong>, allows configuring connections so that the same request can be executed more than once (1 is still the default though).</li>
<li><strong>Fixed all timestamp bugs</strong> (no more -2 hours ago on comments, we hope...)</li>
</ul>
<p>This release marks the first release where we don't only focus on database production access but also provide a feature that allows running bash commands on your kubernetes cluster.
This feature is a bit of a change in direction for kviklet as DB access has been the main focus point fo Kviklet so far. But conceptually it does make sense that you would want to audit all your production access and not just the database access. We are excited to see how this feature is received and if it will be used by users. We also believe the is a lot of potential to expand into this direction and cover more use cases and different technology in the future if this works well.</p>
<p>The next release will focus on improving the experience around adding roles and permissions. Currently if you do not want to use our default setup of roles you run into a bit of an ugly UI and probably have no idea what to do there. For 0.4 we plan to change that and make this experience easier and way more intuitive. The permission system itself might also need a bit of an overhaul.</p>
<p>If you have any feedback or feature requests, please don't hesitate to reach out to us via a <a href="https://github.com/kviklet/kviklet" target="_blank" rel="noopener noreferrer">github issue</a> or on our webpage. We are always happy to hear from users and improve the product based on feedback.</p>]]></content>
        <author>
            <name>Jascha Beste</name>
            <uri>https://www.linkedin.com/in/jaschabeste/</uri>
        </author>
        <category label="ReleaseNotes" term="ReleaseNotes"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Should Developers have production access?]]></title>
        <id>https://kviklet.dev/blog/should-engineers-have-production-access</id>
        <link href="https://kviklet.dev/blog/should-engineers-have-production-access"/>
        <updated>2024-04-02T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Devops and Agile vs Compliance]]></summary>
        <content type="html"><![CDATA[<p>I asked myself this question at my first job at Scalable Capital, 4 years ago. I had started at a FinTech startup/scaleup with somewhere between 50 and 100 engineers, enthusiastic about DevOps and a <strong>You build it, you run it mindset</strong>, which I learned about in my software engineering education in university.<br>
<!-- -->But reality hit hard. You can't simply give every engineer full production access, justifying lax credential management with <em>We want to give people <strong>ownership and trust</strong></em>.</p>
<p>Yes, you want to hire smart people as a leader, and you need to trust your engineers for them to be productive. But even if your hiring is perfect and you never hire anyone that's malicious, the <strong>greatest minds make mistakes</strong> and giving every developer access to production environments will be an issue eventually.<br>
<!-- -->This doesn't have to be leaking a credential or leaving their Macbook open at a Starbucks. This can even be running the <code>DROP TABLE;</code> statement on the production database instead of the development environment.
And I am not making these scenarios up, this happens in the real world even to companies like <a href="https://about.gitlab.com/blog/2017/02/10/postmortem-of-database-outage-of-january-31/" target="_blank" rel="noopener noreferrer">GitLab</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-do-developers-need-access-to-production">Why do developers need access to production?<a href="https://kviklet.dev/blog/should-engineers-have-production-access#why-do-developers-need-access-to-production" class="hash-link" aria-label="Direct link to Why do developers need access to production?" title="Direct link to Why do developers need access to production?">​</a></h2>
<p>In some organizations I've heard the argument that developers don't need access to production at all. Actually noone would need it. Or a phrase like: Developers should just write the code and then the operations team will deploy it. But in my opinion this is a very outdated way of thinking. In a modern DevOps style "you build it, you run it" culture, devs need access to the production environment. How else are they supposed to do their job of "running it" or feel any sense of ownership? You don't have to ask someone else for they key to your own car do you?
If you're not convinced yet, here are 3 simple examples scenarios that you can probably relate too:</p>
<ol>
<li>If production is down, e.g. a service is not reachable after a migration failed</li>
<li>A bug has to be investigated, e.g. a user reports that a payment is not being processed</li>
<li>Someone from business wants a report that the BI system doesn't cover yet, e.g. some tax report</li>
</ol>
<p>In all these cases someone has to log in to prod probably connect to the database and run some queries or statements. And usually the best person to solve a problem or help with the adhoc request is the one that actually wrote the code in the first place and knows how the schema is structured and used.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-giving-everyone-access-to-production-is-a-bad-idea">Why giving everyone access to production is a bad idea<a href="https://kviklet.dev/blog/should-engineers-have-production-access#why-giving-everyone-access-to-production-is-a-bad-idea" class="hash-link" aria-label="Direct link to Why giving everyone access to production is a bad idea" title="Direct link to Why giving everyone access to production is a bad idea">​</a></h2>
<p>But as I mentioned earlier, giving everyone access to production systems is a bad idea. And it's not just a security risk, it's also a risk to the stability of the system.
The main security risks with production access are in order of likelyhood:</p>
<ul>
<li><strong>Innocent mistakes</strong>: Running a query on the wrong database system, or even the wrong server, or running an inefficient query that locks the database and brings down a part of the system. Developers execute <code>DROP TABLE;</code> on the wrong database all the time or accidentally run their test suite against the production database...</li>
<li><strong>Accidental leaks</strong>: Developers might accidentally leak credentials by sending them via slack or other messengers. This is a common issue, and as soon as the wrong person gets their hand on the credentials the system is compromised. This can also happen by leaving the laptop open at a starbucks or maybe even by simply getting your luggage stolen at an airport.</li>
<li><strong>Malicious intent</strong>: This is the least likely scenario, but it is a possibility and a desastrous one if it happens. If a developer is disgruntled or even just wants to make a quick buck, they could do a lot of damage. This is especially dangerous if the developer has access to the production database, as they could steal sensitive data, delete user data, or hold the company hostage via ransomware. This of course requires write access.</li>
</ul>
<p>If you start searching for these scenarios you will find a articles for every single one, so I am not making this up. You need to have a sound setup around your production environment, otherwise one of these will eventually happen.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-not-to-do-it">How not to do it<a href="https://kviklet.dev/blog/should-engineers-have-production-access#how-not-to-do-it" class="hash-link" aria-label="Direct link to How not to do it" title="Direct link to How not to do it">​</a></h2>
<p>A common approach is to have an Operations Team handle such topics, or the so called SRE or DevOps team do it.
These teams don't do normal software development but are instead responsible for infrastructure. But giving them the burden of handling database access management usually slows the resolution of problems down since information first has to travel from one team to the other and it's impossible for one team to understand the whole system well enough to be operationally responsbile. It's also very stressful work to be the one that has to fix things permanenlty, and it's not very rewarding either. Firefighting will usually kick up your adrenaline and cortisol levels, but it's not a good way to spend all of your working life.</p>
<p>But somehting is even worse in this setup: It splits the ownership of a function of your software. And this goes very much against the core of a modern devops culture (or, more recently platform engineering).
Splitting ownership causes a variety of problems, most notably:</p>
<ul>
<li><strong>Blame shifting</strong>: If something goes wrong, it's the other team's fault</li>
<li><strong>Lack of understanding</strong>: If you don't have to fix it, you don't have to understand it</li>
<li><strong>Slow feedback loop</strong>: If you have to wait for another team to fix it, you can't learn from your mistakes</li>
<li><strong>Lack of responsibility</strong>: If you're not responsible for it, you don't care about it</li>
<li><strong>Lack of motivation</strong>: If you're not responsible for it, you don't get the satisfaction of fixing it</li>
</ul>
<p>I personally deem the slow feedback loop as the main issue. If a team doesn't have to operate their software they can't learn from their mistakes. And if you can't learn from your mistakes, you can't improve your software engineering practices and skills.
Meaning teams will ship code that is potentially slow, hard on the database, causes inconsistencies in the data or even security vulnerabilities without ever being held accountable for it.</p>
<p>The SRE Team/Devops Team solves it has another issue as well, if a whole developer team gets willy nillly access to production it is also still a security risk. If one of the engineers' credentials gets leaked, the whole system is compromised. Or they accidentally install a malicious package, or even worse, they are malicious themselves.
This happened at <a href="https://blog.lastpass.com/2023/03/security-incident-update-recommended-actions/" target="_blank" rel="noopener noreferrer">LastPass earlier in 2023</a>:</p>
<blockquote>
<p>Incident 2 Summary: The threat actor targeted a senior DevOps engineer by exploiting vulnerable third-party software. The threat actor leveraged the vulnerability to deliver malware, bypass existing controls, and ultimately gain unauthorized access to cloud backups. The data accessed from those backups included system configuration data, API secrets, third-party integration secrets, and encrypted and unencrypted LastPass customer data.</p>
</blockquote>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="so-whats-the-solution">So what's the solution?<a href="https://kviklet.dev/blog/should-engineers-have-production-access#so-whats-the-solution" class="hash-link" aria-label="Direct link to So what's the solution?" title="Direct link to So what's the solution?">​</a></h2>
<p>Do you have to decide between a modern, agile workflow and security? Can you not have both?<br>
<!-- -->To a degree, it is in fact often a tradeoff that is made: Introducing more processes, to at least achieve compliance and on the flip side deal with slower developement. But seldomly do these processes actually make the system more secure, resulting in a sort of security theater.</p>
<p>Sadly the alternative is a bit expensive, but it usually makes a lot of sense to invest into more sensible processes around developer access, so hear me out: It involves building up an internal toolstack that allows engineers to safely access production directly. This is in fact what larger companies often end up doing.<br>
<!-- -->I talked to Engineers at AWS and Azure, and both have fully fleshed-out internal applications that allow engineers to shadow each other's sessions when they access production resources. Allowing to pull the plug on each other in case someone attempts something shady. Aslong as developers work together they have rather free reign on what to do in prod but due to having 2 or more people involved in every action, the risk of something going wrong is drastically reduced.</p>
<p>Core Features of a solution like that should be:</p>
<ul>
<li><strong>SSO login</strong>: So no credentials are shared, every modern cloud native tool has this</li>
<li><strong>Extensive Audit trailing</strong>: So at least if something still goes wrong you have a trace</li>
<li><strong>4-Eyes Principle</strong>: This is by far the best measure to actually prevent mistakes*and malicious attacks.</li>
</ul>
<p>But this sounds quite generic, why is there no prebuilt solution out there for this task?<br>
<!-- -->Well there is a few, Most notably <a href="https://github.com/gravitational/teleport" target="_blank" rel="noopener noreferrer">Teleport</a> which at least in the enterprise version could tick all the boxes. But it is also incredibly expensive as well as complex to set up.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="four-eyes-principle">Four Eyes Principle<a href="https://kviklet.dev/blog/should-engineers-have-production-access#four-eyes-principle" class="hash-link" aria-label="Direct link to Four Eyes Principle" title="Direct link to Four Eyes Principle">​</a></h2>
<p>I want to expand a bit on The 4-eyes principle since it is a very powerful tool in security. It is a principle that requires that at least two people approve an action before it can be executed. It makes it much harder for a single person to do something malicious. It is also a very powerful tool in preventing mistakes, as it makes it much more likely that someone will catch a mistake before it is executed.</p>
<p>We use the Principle is software engineering all the time, code reviews are a form of the 4-eyes principle. But it is also used in other fields, e.g. in the military, where two people have to turn a key at the same time to launch a missile. It is also used in banking, where two people have to approve a transaction above a certain amount. So why not use it in production access?</p>
<p>You can even expand on the 4-eyes principle, e.g. by requiring that the two people have to be from different teams, or that they have to be from different departments. This makes it even harder for a single person to do something malicious, as they would have to convince someone from another team to help them. Or you require CTO approval, or approval of 3 people, or 4 people, or 5 people. The possibilities are endless, each step making it harder for a single person to do something malicious, without losing the agility of individuals having direct access to production.</p>
<p>The best part is that you do not end up with a weak link in your system, as you would with a single person having access to production. If one person's credentials get leaked, the system is still secure, as they would need another person to approve their actions. And if one person makes a mistake, the other person can catch it before it is executed.</p>
<p>Of course I would for a startup usually suggest to give every engineer read access and just require a second person for writes, but the principle can be expanded to any level of security that you actually need.</p>
<hr>
<p>So if you're just as baffled as we are at why a tool implementing this principle doesn't yet exist yet in the world and we are left with suboptimal or even insecure practices, feel free to have a look at <a href="https://kviklet.dev/" target="_blank" rel="noopener noreferrer">Kviklet</a> which is my attempt at solving this problem once and for all.</p>]]></content>
        <author>
            <name>Jascha Beste</name>
            <uri>https://www.linkedin.com/in/jaschabeste/</uri>
        </author>
        <category label="Production Access" term="Production Access"/>
        <category label="DevOps" term="DevOps"/>
        <category label="DevSecOps" term="DevSecOps"/>
        <category label="Engineering Culture" term="Engineering Culture"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Safely Accessing Production Databases: A Guide for DevOps Teams]]></title>
        <id>https://kviklet.dev/blog/devops-production-database-access-guide</id>
        <link href="https://kviklet.dev/blog/devops-production-database-access-guide"/>
        <updated>2024-03-14T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Discover best practices for accessing production databases in a DevOps environment, ensuring security and efficiency with tools like Kviklet and the Four-Eyes Principle]]></summary>
        <content type="html"><![CDATA[<p><img loading="lazy" alt="Datacenter" src="https://kviklet.dev/blog/assets/images/burning-datacenter-bf94089dd6ba59f5f50b6c1a09c21c43.webp" title="A burning datacenter" width="1792" height="1024" class="img_CujE border_colored_e1LE"></p>
<p>In the fast-paced world of DevOps, safely accessing production databases is a crucial competency that balances operational efficiency with stringent security measures. This comprehensive guide explores DevOps database access best practices, ensuring your engineering teams can swiftly address issues without compromising on security or system integrity.
We'll cover the importance of giving engineers access, the place of migration tools, analytics, and best practices around maintenance and operational tasks. We'll also look at the role of the Four-Eyes Principle in this post.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="why-is-it-important-to-give-engineers-access-to-production-databases">Why is it important to give engineers access to production databases?<a href="https://kviklet.dev/blog/devops-production-database-access-guide#why-is-it-important-to-give-engineers-access-to-production-databases" class="hash-link" aria-label="Direct link to Why is it important to give engineers access to production databases?" title="Direct link to Why is it important to give engineers access to production databases?">​</a></h3>
<p>We already have a post on this topic, <a href="https://kviklet.dev/blog/should-engineers-have-production-access/">Should Engineers Have Production Access?</a> but let's summarize the key points here.</p>
<ol>
<li>Engineers need production access to ensure they can swiftly resolve issues, such as system downtime, bug investigations, or unautomated processes, directly impacting system performance and reliability.</li>
<li>Granting access fosters a sense of ownership and responsibility for the system, aligning with the DevOps philosophy of "You build it, you run it," which encourages engineers to be intimately involved with their products throughout the whole lifecycle.</li>
<li>However, this access comes with risks, as even the most skilled engineers can make critical mistakes, highlighting the importance of implementing robust security measures and tools that enable safe production access while maintaining system integrity and ensuring sensitive data remains secure.</li>
</ol>
<p>We will touch on how exactly to implement these security measures in the following sections.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="using-migration-tools-for-safe-database-changes">Using Migration Tools for Safe Database Changes<a href="https://kviklet.dev/blog/devops-production-database-access-guide#using-migration-tools-for-safe-database-changes" class="hash-link" aria-label="Direct link to Using Migration Tools for Safe Database Changes" title="Direct link to Using Migration Tools for Safe Database Changes">​</a></h3>
<p>Migration tools are a critical component of the modern DevOps environment, playing a key role in safe production database access. They allow engineers to make changes to the database schema and data without having to manually write SQL. This is important because it allows for a more controlled and repeatable process. It also allows for better collaboration between engineers and the database team.</p>
<p>Different languages and frameworks have different migration tools. For example, Ruby on Rails uses ActiveRecord Migrations, while Django uses Django Migrations. If you use Flask you can use Alembic. These tools allow you to write code that describes the changes you want to make to the database, and then apply those changes to the database.
This is a very useful approach for anything that can be planned and tested in advance. E.g. schema changes, adding new columns, migrating data into a new format, etc.</p>
<p>Running migrations on production should be automated. In fact the same workflow should be true for all environments. E.g. if you write a migration it should automatically run on your dev, staging and production environment or any other ones you might have in between. You can e.g. use kubernetes jobs for this purpose, if your application runs on kubernetes.</p>
<p>A huge benefit of migrations is that they are written as code and managed within your normal code base. This means any changes to the database are versioned and can be reviewed and tested just like any other code change. This guarantess that whatever restrictions you have on your code are also true for your DB access via migrations, and heavily reduces the risk of mistakes, or even malicious changes on this path.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="analytical-tasks">Analytical Tasks<a href="https://kviklet.dev/blog/devops-production-database-access-guide#analytical-tasks" class="hash-link" aria-label="Direct link to Analytical Tasks" title="Direct link to Analytical Tasks">​</a></h3>
<p>Analytical tasks, crucial for data-driven decisions, form another challenge for database security in DevOps. They allow developers and Product Managers as well as business analysts to analyze the products data, but simply giving out the root password is ofcourse not an option.</p>
<p>In a mature setup you will usually find a separate interface for these kind of tasks. This is often a data warehouse or a data lake. This is important because it allows you to separate the analytical workloads from the operational workloads. For smaller startups a simple read replica of the production database might be sufficient. But as soon as you have a significant amount of analytical queries you should consider a separate setup.</p>
<p>The data on this interface can be anonymized or aggregated to protect the privacy of your users. This is important because it allows you to give data access to a wider audience without risking the privacy of your users. This is also important for compliance reasons, as you might have to comply with regulations like GDPR. The fact that this is a separate "read-only" database also makes it a lot safer to give access to a bigger part of your organization.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="maintenance-and-operational-tasks">Maintenance and Operational Tasks<a href="https://kviklet.dev/blog/devops-production-database-access-guide#maintenance-and-operational-tasks" class="hash-link" aria-label="Direct link to Maintenance and Operational Tasks" title="Direct link to Maintenance and Operational Tasks">​</a></h3>
<p>This is the crutch of most setups today and the main reason why developers need to access production databases. If you have a bug in your system, you need to be able to look at the data to understand what went wrong. Same for a performance issue, or if you need to run a report that isn't automated or part of your analytics setup yet. Most developer support tasks need access to the production database systems in one form or another.</p>
<p>So you need to run an ad-hoc query, what now? Most companies we've seen solve this by handing out secrets on a case by case basis to give temporary access. This approach fundamentally goes against the purpose of setting up a devops culture in the first place, which should make Operations and Engineers grow closer together.
And It also doesn't solve the problem of the SRE/Devops team being able to do anything they want on the production database. This is a huge security and also a compliance risk.</p>
<p>To solve this issue you need an access control management workflow. Ofcourse as this is the Kviklet blog I highly suggest you try Kviklet out. It's free and <a href="https://kviklet.dev/blog/kviklet-is-now-mit-licensed/">Open Source</a> The Four-Eyes Principle is a great way to solve this issue. It means that every action on the production database has to be approved by a second person. This is a great way to prevent mistakes and also malicious actions protecting any sensitive information in your databases.
It also alleviates the need for the SRE/Devops team to be on call 24/7, as the developers can now do the work themselves and approve each others requests.</p>
<p>If you have money to drop onto the problem you might also want to consider a tool like Apono, StrongDM or Teleport, which try to solve secure access in general and not just DB access, but also come with a hefty price tag.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="best-practices-for-production-database-workflows">Best Practices for Production Database Workflows<a href="https://kviklet.dev/blog/devops-production-database-access-guide#best-practices-for-production-database-workflows" class="hash-link" aria-label="Direct link to Best Practices for Production Database Workflows" title="Direct link to Best Practices for Production Database Workflows">​</a></h3>
<ol>
<li><strong>Automate as much as possible</strong>: Automation is key to ensuring safe production database access. This includes automating migrations, backups, and monitoring. Automation reduces the risk of human error and ensures that best practices are followed consistently.</li>
<li><strong>Use the Four-Eyes Principle</strong>: As mentioned above, the Four-Eyes Principle is a great way to ensure that all actions on the production database are approved by a second person. This is a great way to prevent mistakes and also malicious actions.</li>
<li><strong>Reduce access to be time bound</strong>: If you have to give out access to the production database, make sure it's time bound. This means that the access is only valid for a certain amount of time. This reduces the risk of someone forgetting to revoke access. So ideally you have a way to give JIT(Just in Time) access to the database in one form or another.</li>
<li><strong>Don't use shared accounts</strong>: This is a basic security principle. Don't use shared accounts. Every person should have their own account and their own access rights. This makes it easier to track who did what and also reduces the risk of someone doing something they shouldn't.</li>
<li><strong>Keep your development workflows in mind</strong>: Whatever we suggest here is only useful if it doesn't get in the way of your developers. If you make it too hard to access the production database, your company will suffer from slowed productivity. This is why we suggest using a tool like Kviklet, which makes it easy to access the production database, but also ensures that best practices are followed.</li>
</ol>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="https://kviklet.dev/blog/devops-production-database-access-guide#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion">​</a></h3>
<p>In conclusion, giving developers access to production databases is a critical part of the job for many devops teams. It's also a topic that can be fraught with risk and giving developers access sounds scary. However, with the right tools and processes in place, it can be done safely and securely. We've covered the importance of giving developers access, the place of migration tools, analytics, and best practices around maintenance and operational tasks. We've also looked at the role of the Four-Eyes Principle in this post. We hope you found this post helpful and that it has given you some ideas for how to improve your own production database workflows.</p>
<p>Ready to enhance your DevOps database access practices? Try Kviklet today for safe production database access and join the community driving the future of database security in DevOps. Star us on <a href="https://github.com/kviklet/kviklet" target="_blank" rel="noopener noreferrer">GitHub</a> or better yet, give us your feedback and an Issue!</p>]]></content>
        <author>
            <name>Jascha Beste</name>
            <uri>https://www.linkedin.com/in/jaschabeste/</uri>
        </author>
        <category label="Production Access" term="Production Access"/>
        <category label="DevOps" term="DevOps"/>
        <category label="DevSecOps" term="DevSecOps"/>
        <category label="Postgres" term="Postgres"/>
        <category label="Open Source" term="Open Source"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Parsing the postgres protocol]]></title>
        <id>https://kviklet.dev/blog/parsing-the-postgres-protocol</id>
        <link href="https://kviklet.dev/blog/parsing-the-postgres-protocol"/>
        <updated>2024-03-10T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[How we built a postgres proxy. Deciphering the postgres protocol to add SSO enabled auditlogging]]></summary>
        <content type="html"><![CDATA[<p>Kviklet as an application already allows you to execute arbitrary SQL statements on your database. However a feedback we heard multiple times is that using a simple web tool for query execution is not the same as e.g. a designated DB access software like Datagrip.</p>
<p>And engineers did not always want to have to approve every individual statement. Especially when debugging a production error, they need break glass kind of access.
We already have a temp access mode that lets you execute any amount of statements for 1 hour. But the UI for this is yah well... lacking. We definitely can't compete with datagrip.</p>
<p>So I wanted to experiment... in theory nothing stops us from starting a proxy server and listening in on the postgres network traffic between a client application and the server. This would allow us to add all the cool kviklet features, like an auditlog on SSO level in a very seemless manner almost unnoticable for the actual engineers that had to connect to prod.</p>
<p>This post is about how this works, I found it interesting to poke around on such a low level of the postgres implementation. So maybe you do too.</p>
<p>Postgres runs on a binary frontend/backend protocol. This traffic is potentially SSL encrypted but if we ignore that,
listening in on the traffic results in fun stuff to read like:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">P�����select name, is_dst from pg_catalog.pg_timezone_names</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">B�����������</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Which is not very useful by itself. As noted above I wanted to figure out which statements the user runs on the DB.
However we can parse the traffic into individual messages to make more sense of them.</p>
<p>If we look at the postgres docs we can for example see that 'P' from the frontend stand for a Parse Message.
Which is defined as such:</p>
<hr>
<blockquote>
<p>Byte1('P')
Identifies the message as a Parse command.</p>
</blockquote>
<blockquote>
<p>Int32
Length of message contents in bytes, including self.</p>
</blockquote>
<blockquote>
<p>String
The name of the destination prepared statement (an empty string selects the unnamed prepared statement).</p>
</blockquote>
<blockquote>
<p>String
The query string to be parsed.</p>
</blockquote>
<blockquote>
<p>Int16
The number of parameter data types specified (can be zero). Note that this is not an indication of the number of parameters that might appear in the query string, only the number that the frontend wants to prespecify types for.</p>
</blockquote>
<blockquote>
<p>Then, for each parameter, there is the following:</p>
</blockquote>
<blockquote>
<p>Int32
Specifies the object ID of the parameter data type. Placing a zero here is equivalent to leaving the type unspecified.</p>
</blockquote>
<hr>
<p>This however isn't a statement execution by itself which is what I wanted to track in Kviklet. An execution always consists of a Parse Message, followed by a Bind message that binds specific parameters. Only once this has been done an Execute message is sent.</p>
<p>Now the fact that the statement is first send with placeholder params which are later binded is a bit problematic for me. Afterall I want to add the whole statement to the auditlog with all the parameters filled not just "?" placeholders.</p>
<p>So I also need to parse the Bind message:</p>
<hr>
<blockquote>
<p>Byte1('B')
Identifies the message as a Bind command.</p>
</blockquote>
<blockquote>
<p>Int32
Length of message contents in bytes, including self.</p>
</blockquote>
<blockquote>
<p>String
The name of the destination portal (an empty string selects the unnamed portal).</p>
</blockquote>
<blockquote>
<p>String
The name of the source prepared statement (an empty string selects the unnamed prepared statement).</p>
</blockquote>
<blockquote>
<p>Int16
The number of parameter format codes that follow (denoted C below). This can be zero to indicate that there are no parameters or that the parameters all use the default format (text); or one, in which case the specified format code is applied to all parameters; or it can equal the actual number of parameters.</p>
</blockquote>
<blockquote>
<p>Int16[C]
The parameter format codes. Each must presently be zero (text) or one (binary).</p>
</blockquote>
<blockquote>
<p>Int16
The number of parameter values that follow (possibly zero). This must match the number of parameters needed by the query.</p>
</blockquote>
<blockquote>
<p>Next, the following pair of fields appear for each parameter:</p>
</blockquote>
<blockquote>
<p>Int32
The length of the parameter value, in bytes (this count does not include itself). Can be zero. As a special case, -1 indicates a NULL parameter value. No value bytes follow in the NULL case.</p>
</blockquote>
<blockquote>
<p>Byten
The value of the parameter, in the format indicated by the associated format code. n is the above length.</p>
</blockquote>
<blockquote>
<p>After the last parameter, the following fields appear:</p>
</blockquote>
<blockquote>
<p>Int16
The number of result-column format codes that follow (denoted R below). This can be zero to indicate that there are no result columns or that the result columns should all use the default format (text); or one, in which case the specified format code is applied to all result columns (if any); or it can equal the actual number of result columns of the query.</p>
</blockquote>
<blockquote>
<p>Int16[R]
The result-column format codes. Each must presently be zero (text) or one (binary).</p>
</blockquote>
<hr>
<p>Oof this is getting complicated. So we have parameters and for each parameter we can get the Object ID of the type from the Parse message.<br>
<!-- -->Object IDs are what postgres internally uses to refer to rows. The IDs listed here refer to a table in postgres called pg_type.<br>
<!-- -->In my postgres instance this table contains 500 rows of all kinds of different types my database system supports:</p>
<div class="max-w-full overflow-x-scroll"><table><thead><tr><th>oid</th><th>typname</th><th>typnamespace</th><th>typowner</th><th>typlen</th><th>typbyval</th><th>typtype</th><th>typcategory</th><th>typispreferred</th><th>typisdefined</th><th>typdelim</th><th>typrelid</th><th>typsubscript</th><th>typelem</th><th>typarray</th><th>typinput</th><th>typoutput</th><th>typreceive</th><th>typsend</th><th>typmodin</th><th>typmodout</th><th>typanalyze</th><th>typalign</th><th>typstorage</th><th>typnotnull</th><th>typbasetype</th><th>typtypmod</th><th>typndims</th><th>typcollation</th><th>typdefaultbin</th><th>typdefault</th><th>typacl</th></tr></thead><tbody><tr><td>16</td><td>bool</td><td>11</td><td>10</td><td>1</td><td>true</td><td>b</td><td>B</td><td>true</td><td>true</td><td>,</td><td>0</td><td>-</td><td>0</td><td>1000</td><td>boolin</td><td>boolout</td><td>boolrecv</td><td>boolsend</td><td>-</td><td>-</td><td>-</td><td>c</td><td>p</td><td>false</td><td>0</td><td>-1</td><td>0</td><td>0</td><td>null</td><td>null</td><td>null</td></tr><tr><td>17</td><td>bytea</td><td>11</td><td>10</td><td>-1</td><td>false</td><td>b</td><td>U</td><td>false</td><td>true</td><td>,</td><td>0</td><td>-</td><td>0</td><td>1001</td><td>byteain</td><td>byteaout</td><td>bytearecv</td><td>byteasend</td><td>-</td><td>-</td><td>-</td><td>i</td><td>x</td><td>false</td><td>0</td><td>-1</td><td>0</td><td>0</td><td>null</td><td>null</td><td>null</td></tr><tr><td>18</td><td>char</td><td>11</td><td>10</td><td>1</td><td>true</td><td>b</td><td>Z</td><td>false</td><td>true</td><td>,</td><td>0</td><td>-</td><td>0</td><td>1002</td><td>charin</td><td>charout</td><td>charrecv</td><td>charsend</td><td>-</td><td>-</td><td>-</td><td>c</td><td>p</td><td>false</td><td>0</td><td>-1</td><td>0</td><td>0</td><td>null</td><td>null</td><td>null</td></tr><tr><td>19</td><td>name</td><td>11</td><td>10</td><td>64</td><td>false</td><td>b</td><td>S</td><td>false</td><td>true</td><td>,</td><td>0</td><td>raw_array_subscript_handler</td><td>18</td><td>1003</td><td>namein</td><td>nameout</td><td>namerecv</td><td>namesend</td><td>-</td><td>-</td><td>-</td><td>c</td><td>p</td><td>false</td><td>0</td><td>-1</td><td>0</td><td>950</td><td>null</td><td>null</td><td>null</td></tr><tr><td>20</td><td>int8</td><td>11</td><td>10</td><td>8</td><td>true</td><td>b</td><td>N</td><td>false</td><td>true</td><td>,</td><td>0</td><td>-</td><td>0</td><td>1016</td><td>int8in</td><td>int8out</td><td>int8recv</td><td>int8send</td><td>-</td><td>-</td><td>-</td><td>d</td><td>p</td><td>false</td><td>0</td><td>-1</td><td>0</td><td>0</td><td>null</td><td>null</td><td>null</td></tr></tbody></table></div>
<p>Now this is relevant because in the Bind message the docs refer to the params formatter
codes. If the code is 1 the format is binary. Meaning I don't get the UTF-8 version
of the parameter but instead just a binary value. I need to know what kind of type
the parameter is so that I can transform it to a string.</p>
<p>Since my code is kotlin the formatting for that looks like this:</p>
<div class="language-kotlin codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-kotlin codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token string-literal singleline string" style="color:rgb(255, 121, 198)">"bool"</span><span class="token plain"> </span><span class="token operator">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">bytes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">==</span><span class="token plain"> </span><span class="token number">0x01</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">toByte</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">toString</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token string-literal singleline string" style="color:rgb(255, 121, 198)">"char"</span><span class="token plain"> </span><span class="token operator">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    bytes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">toInt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">toChar</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">toString</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token string-literal singleline string" style="color:rgb(255, 121, 198)">"name"</span><span class="token plain"> </span><span class="token operator">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    bytes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">toHexString</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token string-literal singleline string" style="color:rgb(255, 121, 198)">"int8"</span><span class="token plain"> </span><span class="token operator">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    ByteBuffer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">wrap</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">bytes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">long</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">toString</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>With this decyphering done I can now print a query when I receive the Execute Message. This is fun since I can now see all the introspection and settings commands that datagrip executes:
<img loading="lazy" alt="datagrip introspection" src="https://kviklet.dev/blog/assets/images/datagrip_introspection-945b9e7bce4b4a6ddc5cdf5e31d233ba.png" width="1736" height="1206" class="img_CujE border_colored_e1LE"></p>
<p>Now for my purpose that wasn't quite enough. Just proxying the traffic is only useful if the engineer already has the password to production. However we want to avoid this since this often leads to password sharing and thereby access inflation over time.</p>
<p>Instead I want to integrate my proxy with the kviklet user management, which could also be an SSO provider (google or keycloak). For this I had to implement the login process of the postgres protocol.</p>
<p>Postgres supports a miriad different ways of login in, there is the old way of just sending a username and password via plaintext, there is an md5 hashed version and there is newer options like SCRAM which is defined in <a href="https://datatracker.ietf.org/doc/html/rfc7677" target="_blank" rel="noopener noreferrer">RFC-7677</a>.
Since this is a beta and I want to add SSL later anyways, I simply went with the md5 version, this is also what my locally hosted postgres instance was using so it was easier to reimplement.</p>
<p>The flow is the following:</p>
<ol>
<li>The client sends a startup message containing a user a desired database and a bunch of meta information.</li>
<li>The server responds with an Authentication Request that contains a salt.</li>
<li>The client hashes the username + password + salt and sends it to the server.</li>
<li>If everything is correct the server respondsw with AuthenticationOK + ReadyForQuery messages.</li>
</ol>
<p>After this flow I can again forward all messages to my original postgres connection. This one I btw manage directly via jdbc so I don't have to implement any of the authentication logic on that side.</p>
<p>The exact flow is a bit more complex but you can look at the details in the code if you'd like to:
<a href="https://github.com/kviklet/kviklet/blob/main/backend/src/main/kotlin/dev/kviklet/kviklet/proxy/postgres/PostgresProxy.kt" target="_blank" rel="noopener noreferrer">https://github.com/kviklet/kviklet/blob/main/backend/src/main/kotlin/dev/kviklet/kviklet/proxy/postgres/PostgresProxy.kt</a></p>
<p>With this implemented I can now generate a random password that is only valid for 1 hour, start the proxy with it and forward all traffic to e.g. the root user. All without having to share the password for the root user and with all statements logged in our auditlog. Pretty cool right?</p>
<p>Note this is all quite experimental and still needs some further work before I'd call it production ready. But feel free to play around with it and let me know if you find any problems in a github issue!</p>]]></content>
        <author>
            <name>Jascha Beste</name>
            <uri>https://www.linkedin.com/in/jaschabeste/</uri>
        </author>
        <category label="Production Access" term="Production Access"/>
        <category label="DevOps" term="DevOps"/>
        <category label="DevSecOps" term="DevSecOps"/>
        <category label="Postgres" term="Postgres"/>
        <category label="Open Source" term="Open Source"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Kviklet is now under MIT License]]></title>
        <id>https://kviklet.dev/blog/kviklet-is-now-mit-licensed</id>
        <link href="https://kviklet.dev/blog/kviklet-is-now-mit-licensed"/>
        <updated>2024-02-28T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[We decided to open source Kviklet and not found a company (for now)]]></summary>
        <content type="html"><![CDATA[<p>We've decided to license all our code under MIT and make it fully open-source. With this decision also comes the realization that it is unlikely we will establish a company based on Kviklet.
In this post we are sharing some learnings from our journey and what's next for Kviklet.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-problem-space-and-market-feedback">The Problem Space and Market Feedback<a href="https://kviklet.dev/blog/kviklet-is-now-mit-licensed#the-problem-space-and-market-feedback" class="hash-link" aria-label="Direct link to The Problem Space and Market Feedback" title="Direct link to The Problem Space and Market Feedback">​</a></h2>
<p>Our initial observation was clear: database access, and production access in general, represents a significant hurdle across the tech industry. The existing solutions, including StrongDM, Teleport, and Apono, are not only complex but also carry a hefty price tag. However, as we delved deeper, we discovered that awareness of this problem varies greatly, and so does the willingness to pay for a solution. Highly regulated industries showed readiness to invest in complex, expensive solutions, whereas less regulated sectors remained largely oblivious to the issue, showing little interest in paying for such tools.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-reality-of-selling-an-open-source-and-self-hosted-tool">The Reality of Selling an Open Source and Self-Hosted Tool<a href="https://kviklet.dev/blog/kviklet-is-now-mit-licensed#the-reality-of-selling-an-open-source-and-self-hosted-tool" class="hash-link" aria-label="Direct link to The Reality of Selling an Open Source and Self-Hosted Tool" title="Direct link to The Reality of Selling an Open Source and Self-Hosted Tool">​</a></h2>
<p>Selling an open-source and self-hosted tool itself is much different from selling a typical SaaS solution. Telling someone about your product that they then have to install on their own infrastructure instead of a simple "Login with Google"-button on some website, was a significant hurdle in selling. For a security tool like ours, there was, however, no way around it, hosting your database access on someone else's infrastructure is simply way too risky.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-security-sector-itself">The Security Sector itself<a href="https://kviklet.dev/blog/kviklet-is-now-mit-licensed#the-security-sector-itself" class="hash-link" aria-label="Direct link to The Security Sector itself" title="Direct link to The Security Sector itself">​</a></h2>
<p>The security sector, in particular, presents a "cold start" problem. Our tool, designed to be simple and appealing to small companies, didn't resonate with its intended audience. Small companies are often indifferent to security, and larger companies seek solutions with a proven track record—leaving us in a catch-22 situation. We also do not want to build a generic security tool, but a tool that is specifically designed for database access. Because this is where we think the building around the four-eyes principle is most important and presents a significant advantage over other tools.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="compliance-sells-better-than-actual-security">Compliance sells better than actual security<a href="https://kviklet.dev/blog/kviklet-is-now-mit-licensed#compliance-sells-better-than-actual-security" class="hash-link" aria-label="Direct link to Compliance sells better than actual security" title="Direct link to Compliance sells better than actual security">​</a></h2>
<p>Companies that are regulated or try to maintain/achieve specific certification are much more likely to buy a security tool. This is not because they are more secure, but because they have to prove that they are secure. This is a very important distinction to make. As an early engineering-led product we heavily focused on the security aspect of our solution. We could also explain why the implementation of this workflow is secure and companies should use it, but decision makers often didn't care about actual security but what it could gain them on paper.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="open-source-not-the-amplifier-we-hoped-for">Open Source: Not the Amplifier We Hoped For<a href="https://kviklet.dev/blog/kviklet-is-now-mit-licensed#open-source-not-the-amplifier-we-hoped-for" class="hash-link" aria-label="Direct link to Open Source: Not the Amplifier We Hoped For" title="Direct link to Open Source: Not the Amplifier We Hoped For">​</a></h2>
<p>Making Kviklet open-source did not significantly boost our visibility or adoption. While platforms like Reddit, LinkedIn, and Twitter offered some traction, most leads came through direct networking, cold outreach, or meetups. Nonetheless, the community's engagement did lend us some credibility. I also believe that this is a long-term investment and that the community and visibility will grow over time.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="security-has-a-difficult-to-prove-roi">Security has a difficult to prove ROI<a href="https://kviklet.dev/blog/kviklet-is-now-mit-licensed#security-has-a-difficult-to-prove-roi" class="hash-link" aria-label="Direct link to Security has a difficult to prove ROI" title="Direct link to Security has a difficult to prove ROI">​</a></h2>
<p>One of the most challenging aspects we've encountered is demonstrating the return on investment (ROI) for security solutions. Especially in a market that often prioritizes immediate, tangible benefits, the preventative and intangible nature of security investments makes it a hard sell. This challenge is compounded in environments where efficiency and cost-effectiveness are paramount. Companies are busy trying to cut costs, reducing head count, and finding immediate efficiencies which Kviklet only provides if your current workflow is inefficient.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="whats-next-for-kviklet">What’s Next for Kviklet?<a href="https://kviklet.dev/blog/kviklet-is-now-mit-licensed#whats-next-for-kviklet" class="hash-link" aria-label="Direct link to What’s Next for Kviklet?" title="Direct link to What’s Next for Kviklet?">​</a></h2>
<p>Despite these challenges, we still believe Kviklet is a great tool and solution. We will continue to develop features that we find cool and useful, dedicating our free time to this passion project. We are also open to contributions and eager to support anyone interested in enhancing Kviklet. Companies now have complete freedom to use Kviklet, and we stand ready to assist with any required support or specific feature development. Who knows maybe in the future there will be other opportunities for us to make Kviklet a success.</p>]]></content>
        <author>
            <name>Dan Nguyen</name>
            <uri>https://www.linkedin.com/in/dan-nguyen-ai/</uri>
        </author>
        <author>
            <name>Jascha Beste</name>
            <uri>https://www.linkedin.com/in/jaschabeste/</uri>
        </author>
        <category label="Startup" term="Startup"/>
        <category label="Open Source" term="Open Source"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[How Do Companies Fare When Building Their Products Open Source?]]></title>
        <id>https://kviklet.dev/blog/Companies-building-their-products-open-source</id>
        <link href="https://kviklet.dev/blog/Companies-building-their-products-open-source"/>
        <updated>2023-11-27T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Terraform Drama vs Gitlab Stability - Why do some companies work well with open source and others don't?]]></summary>
        <content type="html"><![CDATA[<p>Open source is core to the modern engineering world. In one way or another, <em>everything runs on Linux or Android</em>, or at the very least, is developed with tools that are available as open source. This hasn't gone unnoticed in the startup world, companies are being founded with a core product that is open source, sometimes funded purely based on GitHub Stars with no active revenue streams.</p>
<p>But I wonder if this actually makes a lot of sense, or if open source isn't by design the more "communist" approach to software development where everyone can contribute and use a tool for free. Which doesn't cooperate well with the goal of building a company that wants to make money.</p>
<p>There have been some interesting developments in recent times with open source-based companies. In March 2022 Snowflake bought Streamlit for $800M. Streamlit at the time was a very hot data visualization tool used by data analysts to easily build interactive web pages that allowed users to explore their analysis. The project had 15.000 stars at the time of exit, and no relevant revenue that would justify this valuation.</p>
<p>These days that doesn't fly anymore, tech valuations have shrunk and especially if you don't have significant cash flow you're in for a hard time. Multiple projects have struggled with this. I've recently worked in the data/analytics area so I am more aware of events there but I'm sure that this is a cross industry trend.</p>
<p>I want to look at "Open source Companies" and how their decision to go open source has played out.</p>
<p>Airbyte is a data integration platform that is partially open source-based, the initial proposition was to build a tool that can integrate all kind of data from different APIs. The connectors themselves should be truly open source while the orchestration layer was licensed.</p>
<p>Airbyte recently realized that this decision led to competitors using their open source connectors as well. Consequently they changed the licensing on the most important connectors (databases) so that only Airbyte themselves are allowed to offer them as a service. This didn't go great with the community and makes the licensing less transparent, making it unclear which parts of Airbyte remain truly open source.</p>
<p>I also believe that the initial reason for starting open source was to make use of the community. Essentially collecting free work that builds into Airbyte product. No one wants to build hundreds of connectors inhouse; it's simply too costly. I doubt this plan will work very well with connectors that are now no longer truly open source. After all, who is willing to contribute code to a company without compensation?"</p>
<p><img loading="lazy" alt="Headline of meltano enabling airbyte connectors" src="https://kviklet.dev/blog/assets/images/meltano-headline-7df0afc2bb430011cc083a5209fc7a80.png" width="2108" height="774" class="img_CujE border_colored_e1LE"></p>
<blockquote>
<p>Surely Airbyte did not like this headline</p>
</blockquote>
<p>Only very recently HashiCorp's Terraform went a similar route. It looks like too many competitors to Terraform's cloud offering have crept up. So they decided to lock down the licensing in an attempt to hinder the competition. Terraform had previously benefited very heavily from being this open and transparent as it has become the de facto standard for infrastructure as code. Pulumi and AWS CloudFormation are the only somewhat serious competitors on that regard, but they are both much smaller or limited (as CloudFormation only works for AWS). But what do you do if everyone uses your tool, but no one is willing to pay for it and even if they do pay they choose another vendor?</p>
<p>In response, Terraform took a desperate measure, altering the very thing that had contributed to their success - they restricted the open source license. The community sentiment is split about this decision; some people don't care, while others are outraged. Competitors of Terraform Cloud, which had previously built upon what HashiCorp and the open source community developed, saw no alternative but to fork the repository and initiate their own project, called OpenToFu. The name isn't well liked by a lot of engineers but time will tell how this project split plays out. Did HashiCorp shoot themselves in the foot? Can the community that made terraform big in the first place also bring them down in the same fashion?</p>
<p><img loading="lazy" alt="A reddit comment about opentofu being a terrible name" src="https://kviklet.dev/blog/assets/images/reddit_comment-be5c9715e730eb11ebe1b7dc4fed8111.png" width="1422" height="278" class="img_CujE border_colored_e1LE"></p>
<blockquote>
<p>Some sentiment over OpenTofu</p>
</blockquote>
<p>There is more examples of license changes in the history of tech (ElasticSearch, anyone?); sometimes they go well, sometimes not. The change itself is rarely taken positively by the public and often hurts the image of a company.</p>
<p>These examples make me wonder, is it even worth it to build a company based on an open-source product? If the community bonus can just as easily turn into a curse, do you really want to be put at their mercy?</p>
<p>Some companies seem to be more successful at managing the open source offerings, the most prominent example is GitLab, I believe. GitLab was started as an open source project and only turned into a company afterwards, but it seems to manage the split rather cleanly so far. GitLab also offers a bunch of licensing options you can either use their cloud Saas hosting (with a typical free option) or you self host, but you can also self host and pay for an enterprise license. Some companies do not want their code to live in the cloud. GitLab is very intentional about what features they put in which version. But I also don't see GitLab benefiting particularly from open source contributions. Sure someone will fix a bug every now and then, but would the company work without the tool being open source? Probably yes.</p>
<p>I think this is a very key takeaway when deciding to go open source or not: Your business needs to work without the help of the open-source community. Yes sure, transparency is great, and if people love your software and want to help then it's amazing if they can do so. But if your product hinges on the free distribution via community building or the 'free work' from open source developers, you are playing with fire.</p>
<p>My co-founders and I are currently building a piece of software and we have decided to go with the open source approach for a part of our software (typical Open Core). But the goal here isn't that we want the community to do the marketing for us or build our product (although any of these effects are of course appreciated if they happen), we are building a security critical tool and security software should be secure by design not by obscurity. In this way open source is our way of fostering trust.</p>
<p>Moreover it will allow companies that don't have the budget to invest into security to start with a sensible safe solution without any investment. We couldn't gain these companies as a customer anyway, but letting them sit with unsafe practices is not a great solution either.</p>
<p>I am personally a big fan of open source as a concept, but I don't like businesses trying to take advantage of the ecosystem and community.</p>]]></content>
        <author>
            <name>Jascha Beste</name>
            <uri>https://www.linkedin.com/in/jaschabeste/</uri>
        </author>
        <category label="Startup" term="Startup"/>
        <category label="Open Source" term="Open Source"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Is Database Access Broken by Design? ]]></title>
        <id>https://kviklet.dev/blog/is-database-access-broken-by-design</id>
        <link href="https://kviklet.dev/blog/is-database-access-broken-by-design"/>
        <updated>2023-10-04T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Creating Awareness for Overlooked Insecurities in Data Practice.]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorWithStickyNavbar_LWe7" id="creating-awareness-for-overlooked-insecurities-in-data-practice">Creating Awareness for Overlooked Insecurities in Data Practice<a href="https://kviklet.dev/blog/is-database-access-broken-by-design#creating-awareness-for-overlooked-insecurities-in-data-practice" class="hash-link" aria-label="Direct link to Creating Awareness for Overlooked Insecurities in Data Practice" title="Direct link to Creating Awareness for Overlooked Insecurities in Data Practice">​</a></h2>
<p><img loading="lazy" alt="A digital vault as an analogy to a database, treasuring the most valuable assets of an organization. Created with Stable Diffusion" src="https://kviklet.dev/blog/assets/images/luminous-digital-vault_sm-4c6a862c892014c2536b9239c72e5d60.png" title="A digital vault as an analogy to a database, treasuring the most valuable assets of an organization. Created with Stable Diffusion" width="1344" height="768" class="img_CujE border_colored_e1LE">
<em>A digital vault as an analogy to a database, treasuring the most valuable assets of an organization. Created with Stable Diffusion</em></p>
<blockquote>
<p>This was our first blog article, originally published on <a href="https://www.linkedin.com/pulse/database-access-broken-design-daniel-nguyen/" target="_blank" rel="noopener noreferrer">LinkedIn</a></p>
</blockquote>
<p>In today's digital age, database access remains a vulnerable aspect for many organizations. Think of databases as the vaults storing a company's most valuable assets - personal data (PII), proprietary data, crypto keys, and other sensitive information. Yet, the reality is that the way organizations handle database access is far from secure.</p>
<hr>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="table-of-content">Table of content:<a href="https://kviklet.dev/blog/is-database-access-broken-by-design#table-of-content" class="hash-link" aria-label="Direct link to Table of content:" title="Direct link to Table of content:">​</a></h4>
<ul>
<li><a href="https://kviklet.dev/blog/is-database-access-broken-by-design#creating-awareness-for-overlooked-insecurities-in-data-practice">Creating Awareness for Overlooked Insecurities in Data Practice</a>
<ul>
<li><a href="https://kviklet.dev/blog/is-database-access-broken-by-design#table-of-content">Table of content:</a></li>
<li><a href="https://kviklet.dev/blog/is-database-access-broken-by-design#past-data-breaches-highlight-importance-of-secure-dataaccess">Past Data Breaches Highlight Importance of Secure Data&nbsp;Access</a></li>
<li><a href="https://kviklet.dev/blog/is-database-access-broken-by-design#root-cause-are-insecure-practices">Root Cause are Insecure Practices</a></li>
<li><a href="https://kviklet.dev/blog/is-database-access-broken-by-design#manual-data-access-more-frequent-and-risky-than-assumed">Manual Data Access: More Frequent and Risky Than Assumed</a></li>
<li><a href="https://kviklet.dev/blog/is-database-access-broken-by-design#database-access-management-the-current-landscape">Database Access Management: The Current Landscape</a></li>
<li><a href="https://kviklet.dev/blog/is-database-access-broken-by-design#balancing-productivity-andsecurity">Balancing Productivity and&nbsp;Security</a></li>
<li><a href="https://kviklet.dev/blog/is-database-access-broken-by-design#a-call-toaction">A Call to&nbsp;Action</a></li>
<li><a href="https://kviklet.dev/blog/is-database-access-broken-by-design#references">References</a></li>
</ul>
</li>
</ul>
<hr>
<a id="past-data-breaches"></a>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="past-data-breaches-highlight-importance-of-secure-dataaccess">Past Data Breaches Highlight Importance of Secure Data&nbsp;Access<a href="https://kviklet.dev/blog/is-database-access-broken-by-design#past-data-breaches-highlight-importance-of-secure-dataaccess" class="hash-link" aria-label="Direct link to Past Data Breaches Highlight Importance of Secure Data&nbsp;Access" title="Direct link to Past Data Breaches Highlight Importance of Secure Data&nbsp;Access">​</a></h3>
<p>Historically, the compromise of credentials and privileged accounts has been the most prominent reason for notable data breaches. Google researchers found that 41% of compromises in 2022 were to blame on weak passwords, while Mandiant found that credential theft as an entry vector rose from 9% to 14% between 2021 and 2022 [1].</p>
<p>In 2018 the Marriott hotel group detected a data breach that serves as a case in point: Hackers got access to privileged accounts and were able to extract ~500m customer data from the booking database. The breach took place in 2014, but wasn't discovered until 2018 and Marriott subsequently got issued a $24m GDPR fine [2].</p>
<p>But it's not always malicious intent that wreaks havoc: In 2017 GitLab experienced an 18h outage that impacted ~5000 projects worldwide after an engineer executed a command on the wrong database cluster [3]. Or consider the FAA pilot-alerting system outage in 2023 that led to a nationwide ground stop, delaying 34k flights in the US. Engineers accidentally corrupted the live database, forcing the pilot-alerting system to go offline overnight [4].</p>
<a id="insecure-practices"></a>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="root-cause-are-insecure-practices">Root Cause are Insecure Practices<a href="https://kviklet.dev/blog/is-database-access-broken-by-design#root-cause-are-insecure-practices" class="hash-link" aria-label="Direct link to Root Cause are Insecure Practices" title="Direct link to Root Cause are Insecure Practices">​</a></h3>
<p>Throughout our conversations with engineers and CTOs, and our own experience as (cybersecurity-) engineers, we've noticed fundamental flaws in how organizations provide access to data, exposing them to a great risk. We've witnessed immature processes and insecure practices both in formalized processes and day-to-day operations. This is particularly relevant when organizations are solely reliant on the basic tooling that many (SQL-)databases offer, underscoring the urgent need for rectification. Below are the most common flaws, that we've observed:</p>
<ol>
<li>Authentication Lapses: The absence of Single Sign-On or SAML means users need multiple credentials</li>
<li>Shared Accounts: Often, multiple users operate under a single account, making it difficult to trace actions back to individuals</li>
<li>Missing Credential Rotation: Credentials that aren't periodically rotated, increase the window of opportunity for malicious actors to exploit potentially compromised, leaked, or outdated credentials</li>
<li>Neglected Account Decommissioning: When account decommissioning is treated as an afterthought (e.g., when an employee is leaving the company), it results in overlooked shadow and unmanaged accounts, which can be exploited by hackers</li>
<li>Process Circumvention: Some users might bypass standard processes (like using JIRA for access requests) in favor of shortcuts, leading to unmonitored activities</li>
<li>Improper Audit Logs: Without correctly implemented audit logs and monitoring, tracing database activities become challenging</li>
</ol>
<p>Compounding the risks is the absence of rigorous QA in database operations. Typical Software Development Life Cycles (SDLC) involves many steps that can prevent errors from reaching production, including CI/CD pipelines, code tests, and code reviews. However, databases, once granted access, can be freely manipulated in live environments.</p>
<a id="manual-data-access"></a>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="manual-data-access-more-frequent-and-risky-than-assumed">Manual Data Access: More Frequent and Risky Than Assumed<a href="https://kviklet.dev/blog/is-database-access-broken-by-design#manual-data-access-more-frequent-and-risky-than-assumed" class="hash-link" aria-label="Direct link to Manual Data Access: More Frequent and Risky Than Assumed" title="Direct link to Manual Data Access: More Frequent and Risky Than Assumed">​</a></h3>
<p>As we deep dive into the challenges associated with data access, we've pinpointed the most common scenarios for data access.</p>
<p>We're intentionally excluding BI/data science and programmatic data access scenarios from our discussion. While these domains present distinct security challenges, they benefit from more mature processes and tooling:</p>
<ul>
<li>BI and data science: Frequently facilitated through data lakes, which store a copied subset of the live data, often anonymized or pseudonymized to ensure data privacy. Data lakes are ususally interacted with using analytics tools, such as PowerBI, Tableau, and Python libraries</li>
<li>Programmatic data access: Refers to the systematic ways software applications interact with databases, incl. cloud databases and SQL. Key methodologies include using dedicated APIs or SQL queries. Authentication frequently uses username/password, API tokens or client certificates</li>
</ul>
<p>What we want to highlight are manual database access scenarios, as we think that the existing procedures around authentication and authorization are fundamentally flawed. Below are the most common situations in which manual database access occur:</p>
<ul>
<li>Incident resolution and 3rd level-support: The ideal scenario involves engineers using specialized tools to troubleshoot and resolve issues. However, what we see is that tools are often unavailable or insufficient, especially for complex incidents. In such cases, engineers require direct production access to diagnose and fix bugs, or probe into issues reported by users</li>
<li>Feature Development: While developing new features, engineers often need to understand the current data distribution (e.g., for performance evaluations) or validate assumptions about the data. To facilitate this, engineers are either provided access to a replica database or granted direct access to the live database</li>
<li>Ad-hoc access for reporting: Business analysts sometimes require direct access to production databases, when the data in the BI data lakes is insufficient, not up-to-date, or changed in a way that it corrupted reporting dashboards</li>
</ul>
<p>In short, manual database access occurs a lot more frequently than many realize and carries most of the problems we highlighted before. Let's take a closer look at how organizations manage and orchestrate manual database access.</p>
<a id="current-landscape"></a>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="database-access-management-the-current-landscape">Database Access Management: The Current Landscape<a href="https://kviklet.dev/blog/is-database-access-broken-by-design#database-access-management-the-current-landscape" class="hash-link" aria-label="Direct link to Database Access Management: The Current Landscape" title="Direct link to Database Access Management: The Current Landscape">​</a></h3>
<p>Through our research, we've identified a spectrum of approaches to managing production database access, ranging from early stage approaches to those adopted by mature organizations:</p>
<ol>
<li>No controls: The norm in young and unregulated companies, where access is freely granted upon request and credentials are often provided unencrypted and shared amongst employees</li>
<li>Access review process in place: While there are ticketing systems like JIRA workflows in place to review, approve, and document access requests, they often lack strict enforcement. Moreover, procedures of account decommissioning and credential rotation are commonly neglected and treated as a secondary concern</li>
<li>Ops team as intermediaries: Some companies deploy dedicated ops teams to serve as intermediaries. They ususally create and provide access to data replications/ data lakes that add to storage expenses, or handle data requests firsthand. This reliance on the ops team creates a bottleneck, preventing engineers from engaging in devops practices. Furthermore, due to their elevated access privileges, these team members can become prominent targets for cyberattacks</li>
<li>Internal ad-hoc solutions: While developed in-house and tailored to the organization's needs, these solutions can consume significant developer resources for development and maintenance. We've come across a range of inventive methods, from GitOps workflows to using AWS Lambdas for granting access. Although these methods effectively address specific security challenges, they might not cover all aspects comprehensively</li>
<li>Commercial software solutions: In 2023, the market for commercial access management and data security solutions is estimated to be worth $25bn. These solutions typically offer features like RBAC, SSO, dynamic secret generation, and auditing [5]. However, they can be challenging to integrate, lack flexibility in customization, and often carry a hefty price tag</li>
<li>Holistic custom platforms: We've seeen mature (tech) companies developing comprehensive platforms for database access with features like time-limited access and column/row restrictions. Additionally, some have implemented review and approval mechanisms on query level, upholding the "four-eyes principle" for enhanced security</li>
</ol>
<p>In conclusion, while the landscape of database access management is diverse and ever-changing, commercial solutions haven't provided the needed balance between security and developer experience/ productivity. Given their complexity and pricing, it's no surprise that many small to medium-sized organizations lean towards building in-house solutions and processes.</p>
<a id="productivity-vs-security     "></a>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="balancing-productivity-andsecurity">Balancing Productivity and&nbsp;Security<a href="https://kviklet.dev/blog/is-database-access-broken-by-design#balancing-productivity-andsecurity" class="hash-link" aria-label="Direct link to Balancing Productivity and&nbsp;Security" title="Direct link to Balancing Productivity and&nbsp;Security">​</a></h3>
<p>The challenge facing businesses as they grow is speed versus risk: Grant extensive production access, thereby embracing the modern ethos of "You build it, you run it", but risk enlarging the attack surface. Conversely, strictly locking down access to the production environment might bolster security but slows down the pace of development and incident resolution. Such stringent measures, though appearing safe, aren't completely secure. High-privilege accounts still exist and pose a risk, and the potential for innocent mistakes remains.</p>
<p>In our observations, it's common for startups to begin with a more trust-based and liberal approach to production access, to allow for agility and rapid development in the early stages. However, as these companies scale and mature, there's a shift towards more stringent access controls, often driven by regulatory requirements.</p>
<p>In hyper-growth startups in particular the growth often outpaces their ability to implement mature processes. As a result, there can be a period where these companies find themselves in a transitional phase --- moving from the unrestricted environment of a startup to a more structured and compliant operational model.</p>
<a id="cta"></a>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="a-call-toaction">A Call to&nbsp;Action<a href="https://kviklet.dev/blog/is-database-access-broken-by-design#a-call-toaction" class="hash-link" aria-label="Direct link to A Call to&nbsp;Action" title="Direct link to A Call to&nbsp;Action">​</a></h3>
<p>Witnessing the shortcomings first hand at previous organizations we are creating <a href="https://kviklet.dev/" target="_blank" rel="noopener noreferrer">Kviklet</a>, developing an open-source solution inspired by the most mature workflows we have seen. We believe that a community-driven tool can bridge current gaps to improve security, while improving developer experience.</p>
<p>If you resonate with these challenges and have insights into how database access should be managed, get in touch with us and let's co-create a tool that benefits the entire DevOps community!</p>
<hr>
<a id="references"></a>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="references">References<a href="https://kviklet.dev/blog/is-database-access-broken-by-design#references" class="hash-link" aria-label="Direct link to References" title="Direct link to References">​</a></h3>
<ol>
<li><a href="https://cloud.google.com/blog/transform/how-leaders-can-reduce-risk-shutting-down-security-theater/" target="_blank" rel="noopener noreferrer">Google, "How leaders can reduce risk by shutting down security theater", Sep 2023</a></li>
<li><a href="https://www.csoonline.com/article/567795/marriott-data-breach-faq-how-did-it-happen-and-what-was-the-impact.html" target="_blank" rel="noopener noreferrer">CSO Online, "Marriott data breach FAQ: How did it happen and what was the impact?", Feb 2020</a></li>
<li><a href="https://about.gitlab.com/blog/2017/02/10/postmortem-of-database-outage-of-january-31/" target="_blank" rel="noopener noreferrer">GitLab, "Postmortem of database outage of January 31", Feb 2017</a></li>
<li><a href="https://www.faa.gov/newsroom/faa-notam-statement" target="_blank" rel="noopener noreferrer">Federal Aviation Administration, "FAA NOTAM Statement", Jan 2023</a></li>
<li><a href="https://www.gartner.com/en/newsroom/press-releases/2022-10-13-gartner-identifies-three-factors-influencing-growth-i" target="_blank" rel="noopener noreferrer">Gartner, "Gartner Identifies Three Factors Influencing Growth in Security Spending", Oct 2022</a></li>
<li><a href="https://kviklet.dev/" target="_blank" rel="noopener noreferrer">https://kviklet.dev</a></li>
</ol>]]></content>
        <author>
            <name>Dan Nguyen</name>
            <uri>https://www.linkedin.com/in/dan-nguyen-ai/</uri>
        </author>
        <author>
            <name>Jascha Beste</name>
            <uri>https://www.linkedin.com/in/jaschabeste/</uri>
        </author>
        <author>
            <name>Nils Borrmann</name>
            <uri>https://www.linkedin.com/in/nils-borrmann-663883110/</uri>
        </author>
    </entry>
</feed>