<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Archives des Security - dbi Blog</title>
	<atom:link href="https://www.dbi-services.com/blog/category/security/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.dbi-services.com/blog/category/security/</link>
	<description></description>
	<lastBuildDate>Fri, 15 May 2026 19:45:30 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/05/cropped-favicon_512x512px-min-32x32.png</url>
	<title>Archives des Security - dbi Blog</title>
	<link>https://www.dbi-services.com/blog/category/security/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Customer case study &#8211; automating SQL Server TLS Encryption with Ansible and Certificates (Architecture)</title>
		<link>https://www.dbi-services.com/blog/customer-case-study-automating-sql-server-tls-encryption-with-ansible-and-certificates-architecture/</link>
					<comments>https://www.dbi-services.com/blog/customer-case-study-automating-sql-server-tls-encryption-with-ansible-and-certificates-architecture/#respond</comments>
		
		<dc:creator><![CDATA[Amine Haloui]]></dc:creator>
		<pubDate>Fri, 15 May 2026 19:35:21 +0000</pubDate>
				<category><![CDATA[Ansible]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[SQL Server]]></category>
		<guid isPermaLink="false">https://www.dbi-services.com/blog/?p=44594</guid>

					<description><![CDATA[<p>When working with SQL Server environments, securing client connections can become an important requirement, especially when TLS encryption must be implemented using certificates. In this context, a customer asked us to develop an Ansible playbook and role to automate the configuration of TLS for SQL Server. The certificates are generated from the customer PKI and [&#8230;]</p>
<p>L’article <a href="https://www.dbi-services.com/blog/customer-case-study-automating-sql-server-tls-encryption-with-ansible-and-certificates-architecture/">Customer case study &#8211; automating SQL Server TLS Encryption with Ansible and Certificates (Architecture)</a> est apparu en premier sur <a href="https://www.dbi-services.com/blog">dbi Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>When working with SQL Server environments, securing client connections can become an important requirement, especially when TLS encryption must be implemented using certificates. In this context, a customer asked us to develop an Ansible playbook and role to automate the configuration of TLS for SQL Server. The certificates are generated from the customer PKI and provided as PEM files containing the server certificate, the private key, and the certificate chain.</p>



<p>However, some extractions and conversions are required before these certificates can be used on Windows and configured for SQL Server.</p>



<p>Here, the idea is to propose a solution (the architecture) that prepares the certificate, imports it on the SQL Server host, and configures SQL Server to use it.</p>



<p>We will also see how to separate the preparation and activation steps in order to reduce the impact on the SQL Server service.</p>



<p>In this blog post, we will describe the global approach and the Ansible logic used to implement certificate-based TLS encryption for SQL Server.</p>



<h2 class="wp-block-heading" id="h-implementation-logic">Implementation logic</h2>



<p>Before configuring TLS encryption on SQL Server, the first point was to understand the certificate format provided by the customer PKI.</p>



<p>In our case, the generated file is a &lt;machine&gt;.pem file. This file contains the server certificate used for TLS, the private key and the certificate chain with the intermediate and root certificates.</p>



<p>As this format cannot be directly used as-is on the Windows side for SQL Server, some extraction and conversion steps are required.</p>



<p>The general idea is to use the Ansible control node as a working area.</p>



<p>The PEM file is first copied into a temporary folder where the different parts of the certificate are extracted:</p>



<ul class="wp-block-list">
<li>the leaf certificate</li>



<li>the intermediate certificate</li>



<li>the root certificate</li>



<li>the private key</li>
</ul>



<p>These elements are then used to build a PFX file which can be imported on the Windows SQL Server host.</p>



<p>The PFX is installed in the LocalMachine\My certificate store while the intermediate and root certificates are imported into the appropriate Windows certificate stores.</p>



<p>The implementation has been designed around three different execution modes: stage, activate, and full.</p>



<p>The stage mode is used to prepare the certificate without any impact on the SQL Server service. It copies the PEM file, performs the extractions, builds the PFX file, copies it to the managed Windows node and imports the certificates into the Windows certificate stores. No registry change is performed, and the SQL Server service is not restarted. This mode is useful when we want to prepare the server in advance before switching SQL Server to the new certificate.</p>



<p>The activate mode assumes that the certificate is already present on the Windows server. Its role is to configure SQL Server to use the installed certificate and depending on the selected option, restart the SQL Server service or leave the change pending until the next planned reboot.</p>



<p>This can be useful when the certificate activation must be aligned with an existing maintenance window, for example during monthly OS patching.</p>



<p>The full mode executes the complete configuration from end to end. It performs the extraction and conversion steps, imports the certificates, grants the required permissions, configures SQL Server to use the expected certificate, and restarts the SQL Server service only if required. To avoid unnecessary impact, the role relies on the certificate thumbprint. If the expected certificate is already configured, no change is applied and the SQL Server service is not restarted. This behavior is important for idempotency.</p>



<p>For example, if the full mode is executed after an activate mode, nothing should be changed if the certificate is already the correct one. The same logic applies if the playbook is executed by mistake while the certificate has not been renewed.</p>



<p>Another point to manage is the restart of the SQL Server service. SQL Server loads the certificate configuration when the service starts. Therefore, when a new certificate is configured, the change is only effective after a restart of the SQL Server service.</p>



<p>For this reason the role should provide an option to control whether the restart is performed immediately or postponed to the next planned reboot.</p>



<p>We also have to consider DNS aliases. The standard use case is to generate a certificate containing at least the short name and the FQDN of the SQL Server host in the subjectAltName. If DNS aliases are used by client applications, they can also be added to the certificate SAN.</p>



<p>For example:</p>



<pre class="wp-block-code"><code>&#091;alt_names]
DNS.1 = A-WS2022-2.lab.local
DNS.2 = A-WS2022-2</code></pre>



<p>Finally, the customer confirmed that the private key included in the PEM file is not encrypted.</p>



<p>This simplifies the conversion process to PFX, but it also means that the PEM file must be handled carefully during the Ansible execution, especially in temporary folders and during file transfers. With this approach, the role provides a controlled way to prepare, activate, or fully configure TLS encryption for SQL Server while keeping the impact on the SQL Server service under control.</p>



<h2 class="wp-block-heading" id="h-logical-workflow">Logical workflow</h2>



<p>The complete workflow can be represented as follows:</p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="672" height="1024" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2026/05/I3_Wite_Background-672x1024.jpeg" alt="" class="wp-image-44607" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2026/05/I3_Wite_Background-672x1024.jpeg 672w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2026/05/I3_Wite_Background-197x300.jpeg 197w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2026/05/I3_Wite_Background-768x1169.jpeg 768w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2026/05/I3_Wite_Background-1009x1536.jpeg 1009w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2026/05/I3_Wite_Background-1345x2048.jpeg 1345w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2026/05/I3_Wite_Background-scaled.jpeg 1681w" sizes="(max-width: 672px) 100vw, 672px" /></figure>



<h2 class="wp-block-heading" id="h-architecture-summary">Architecture summary</h2>



<p>The certificate manipulation is performed on the Ansible control node.</p>



<p>The Windows certificate import and SQL Server configuration are performed on the managed Windows SQL Server host.</p>



<p>This separation is useful because the PEM processing and PFX generation are handled with Linux tools such as OpenSSL while the certificate installation, private key permissions, registry configuration and SQL Server restart are handled through Windows modules and PowerShell. The design also supports a controlled deployment approach.</p>



<p>The certificate can first be staged without service impact then activated later during a maintenance window.</p>



<p>The full mode can be used when the complete implementation must be executed in a single run. The use of the certificate thumbprint is important for idempotency. It allows the role to detect whether SQL Server is already configured with the expected certificate and avoids unnecessary service restarts when no change is required.</p>



<h2 class="wp-block-heading" id="h-remarks">Remarks</h2>



<p>For certain reasons we do not disclose the code of the created role.</p>



<p>Thank you. <a href="https://www.linkedin.com/in/amine-haloui-76968056/">Amine Haloui</a></p>
<p>L’article <a href="https://www.dbi-services.com/blog/customer-case-study-automating-sql-server-tls-encryption-with-ansible-and-certificates-architecture/">Customer case study &#8211; automating SQL Server TLS Encryption with Ansible and Certificates (Architecture)</a> est apparu en premier sur <a href="https://www.dbi-services.com/blog">dbi Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dbi-services.com/blog/customer-case-study-automating-sql-server-tls-encryption-with-ansible-and-certificates-architecture/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Beyond TDE and TLS: Bridging the Data Security Governance Gap in Lower Environments</title>
		<link>https://www.dbi-services.com/blog/tde-tls-data-security-governance-gap-in-lower-environments/</link>
					<comments>https://www.dbi-services.com/blog/tde-tls-data-security-governance-gap-in-lower-environments/#respond</comments>
		
		<dc:creator><![CDATA[Louis Tochon]]></dc:creator>
		<pubDate>Mon, 27 Apr 2026 20:21:34 +0000</pubDate>
				<category><![CDATA[Delphix]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[delphix]]></category>
		<category><![CDATA[encryption]]></category>
		<guid isPermaLink="false">https://www.dbi-services.com/blog/?p=43973</guid>

					<description><![CDATA[<p>Why one layer is never enough, why dev environments are your biggest GDPR gap, and how to industrialize their governance.</p>
<p>L’article <a href="https://www.dbi-services.com/blog/tde-tls-data-security-governance-gap-in-lower-environments/">Beyond TDE and TLS: Bridging the Data Security Governance Gap in Lower Environments</a> est apparu en premier sur <a href="https://www.dbi-services.com/blog">dbi Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full is-style-rounded"><img decoding="async" width="1408" height="768" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2026/04/Gemini_Generated_Image_8vt09b8vt09b8vt0.png" alt="Conceptual diagram of a secure data pipeline showing production data passing through a governance engine to anonymized dev and staging environments." class="wp-image-44034" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2026/04/Gemini_Generated_Image_8vt09b8vt09b8vt0.png 1408w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2026/04/Gemini_Generated_Image_8vt09b8vt09b8vt0-300x164.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2026/04/Gemini_Generated_Image_8vt09b8vt09b8vt0-1024x559.png 1024w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2026/04/Gemini_Generated_Image_8vt09b8vt09b8vt0-768x419.png 768w" sizes="(max-width: 1408px) 100vw, 1408px" /></figure>



<h2 class="wp-block-heading" id="h-the-multi-layered-threat-why-one-tool-is-never-enough">The Multi-Layered Threat: Why One Tool is Never Enough</h2>



<p>We’ve all left the key in our bike lock at least once. This simple human oversight makes the heaviest chain irrelevant and we often see the exact same logic applied to data environments. Most organizations spend months hardening their production core but leave the keys in the locks of the <em>dev</em> and <em>staging </em>systems that sit right next to it. </p>



<p>The numbers back this up. While 91% of organizations are concerned about their exposure across lower environments, a staggering <span style="text-decoration: underline"><strong>86%</strong> <strong>still allow data compliance exceptions in non-production</strong></span>. This gap between concern and action has real consequences: more than half of these organizations have already experienced a breach or audit failure in their testing and development systems (<a href="https://www.prnewswire.com/news-releases/delphixs-state-of-data-compliance-and-security-report-reveals-54-of-organizations-have-experienced-data-breaches-or-theft-in-non-production-environments-302225897.html">PR Newswire</a>).</p>



<p>Effective security is rarely a single-layer problem. Between the stolen backup that lands in the wrong hands, the analyst running a <code>SELECT</code> on a table they probably shouldn&#8217;t see, and the packet quietly crossing an unsecured network segment, <a href="https://www.fortinet.com/resources/cyberglossary/attack-surface">the attack surface</a> is wide, and no single mechanism covers it all.</p>



<p>Transport Layer Security (TLS), Transparent Data Encryption (TDE), symmetric encryption, dynamic masking, row-level security, data anonymization: for most RDBMS, the options exist and they work. Most teams already have access to at least one of them. The real challenge isn&#8217;t finding a solution; it&#8217;s understanding what each one actually protects, where it breaks down, and whether it survives contact with a production environment.</p>



<h2 class="wp-block-heading" id="h-shadow-environments-the-weakest-link-in-your-data-chain">Shadow Environments: The Weakest Link in Your Data Chain</h2>



<p>Here is the uncomfortable truth: non-production environments are often where security policies are quietly buried. It starts with a backup restored without encryption, or real customer data seeding a dev database <em>&#8220;just for a quick test</em>&#8220;.</p>



<p>The fundamental problem is that most protections assume a controlled environment. Encryption can be bypassed by someone with the right credentials. Masking can be misconfigured. Row-level security doesn&#8217;t help much when the whole database is sitting on a developer&#8217;s laptop.</p>



<h2 class="wp-block-heading" id="h-technical-trade-offs-finding-your-strategic-fit">Technical Trade-offs: Finding Your Strategic Fit</h2>



<p>To make this reasoning concrete, the table below maps six core techniques against the operational criteria that define their success. The goal isn&#8217;t to pick a favorite tool, but to identify which combination actually addresses your specific vulnerabilities.</p>



<figure class="wp-block-table alignfull is-style-stripes"><table><tbody><tr><td class="has-text-align-center" data-align="center"></td><td class="has-text-align-center" data-align="center">Physical File Theft</td><td class="has-text-align-center" data-align="center">Read Access (SELECT)</td><td class="has-text-align-center" data-align="center">Network Sniffing</td><td class="has-text-align-center" data-align="center">Performance Impact</td><td class="has-text-align-center" data-align="center">Granularity</td><td class="has-text-align-center" data-align="center">Applicable in Prod <br>(live data)</td><td class="has-text-align-center" data-align="center">Applicable in DEV</td></tr><tr><td class="has-text-align-center" data-align="center">TLS</td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center">Data packet</td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td></tr><tr><td class="has-text-align-center" data-align="center">TDE</td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center">Column<br>Tablespace<br>Datafile</td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td></tr><tr><td class="has-text-align-center" data-align="center">Symmetric encryption (applicative)</td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center">Field<br>Value</td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td></tr><tr><td class="has-text-align-center" data-align="center">Dynamic Masking</td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center">Column</td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td></tr><tr><td class="has-text-align-center" data-align="center">Row-level security</td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center">Row</td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td></tr><tr><td class="has-text-align-center" data-align="center">Data anonymization</td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center">Field<br>Column</td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td class="has-text-align-center" data-align="center"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td></tr></tbody></table></figure>



<ul class="wp-block-list">
<li><a href="https://en.wikipedia.org/wiki/Transport_Layer_Security">TLS </a>protects data in motion. The moment a packet leaves a server, TLS ensures anyone intercepting it sees encrypted noise. What it doesn&#8217;t do is equally important: it has no opinion about who queries your database or what&#8217;s stored on disk. Once the data arrives, TLS&#8217;s job is done.<br>TLS is now the industry standard for securing data in motion.<br><em>(SQL Server technical blog about TLS <a href="https://www.dbi-services.com/blog/sql-server-how-to-see-your-enable-security-protocols-tls-ssl-dtls-with-a-tsql-query/">here</a>)</em></li>



<li><a href="https://docs.oracle.com/en/database/oracle/oracle-database/19/asoag/introduction-to-transparent-data-encryption.html">TDE </a>encrypts the physical files that make up your database (data files, log files, backups), so that anyone who gets their hands on them without the encryption key can&#8217;t read them. The performance impact is a negligible overhead; in fact, Microsoft for example enables TDE <strong>by default</strong> for all its cloud-based databases.<br><em>(PostgreSQL technical blog about TDE <a href="https://www.dbi-services.com/blog/commercial-postgresql-distributions-with-tde-1-fujitsu-enterprise-postgres-1-setup/">here</a>)</em><br>However, deploying TDE in development is a security best practice, but it quickly becomes an operational nightmare for environment refreshes, especially if you want to use distinct certificates to avoid leaking production secrets into lower environments.</li>



<li><a href="https://learn.microsoft.com/en-us/sql/relational-databases/security/encryption/always-encrypted-database-engine?view=sql-server-ver17">Symmetric encryption</a> is field-level encryption applied directly in the application layer. Unlike TDE, it survives a legitimate SELECT; even a user with full read access sees <a href="https://en.wikipedia.org/wiki/Ciphertext">ciphertext </a>unless they hold the applicative key. The tradeoff is performance: encrypting and decrypting at scale adds up quickly.<br><em>(MongoDB technical blog about Client-side Field Level Encryption <a href="https://www.geeksforgeeks.org/mongodb/mongodb-client-side-field-level-encryption/">here</a>)</em></li>



<li><a href="https://learn.microsoft.com/en-us/sql/relational-databases/security/dynamic-data-masking?view=sql-server-ver17">Dynamic masking</a> doesn&#8217;t encrypt anything. It intercepts query results and replaces sensitive values with masked equivalents based on the user&#8217;s role. Fast, lightweight, zero application changes required. The catch: it only controls what&#8217;s displayed, not what&#8217;s stored. A user with sufficient privileges can bypass it entirely.<br><em>(SQL Server technical blog about dynamic masking <a href="https://www.mssqltips.com/sqlservertip/7887/dynamic-data-masking-in-sql-server-for-sensitive-data-protection/">here</a>)</em></li>



<li><a href="https://database.guide/understanding-row-level-security-rls/">Row-Level Security </a>enforces access at the row level directly inside the database engine. Users see only the rows they&#8217;re allowed to see, regardless of how the query is written. No application changes, no trust placed in the calling layer. The policy lives in the database and applies universally.<br><em>(Oracle technical blog about Virtual Private Database <a href="https://www.dbi-services.com/blog/oracle-virtual-private-database/">here</a>)</em></li>



<li><a href="https://en.wikipedia.org/wiki/Data_anonymization">Data anonymization</a> doesn&#8217;t protect sensitive data, <strong><span style="text-decoration: underline">it eliminates it</span></strong>. Real values are replaced with realistic but fictional equivalents (<a href="https://www.ibm.com/think/topics/synthetic-data">synthetic data</a>), permanently and irreversibly. No encryption key to steal, no masking rule to bypass. Whatever leaks simply isn&#8217;t sensitive anymore. This is why anonymization is the only control that makes unconditional sense in non-production environments. A stolen backup, a misconfigured SELECT, a sniffed packet: <strong>none</strong> of it matters if the data was anonymized before it ever reached a staging environment. We covered how to implement it in practice in <a href="https://www.dbi-services.com/blog/data-anonymization-as-a-service-with-delphix-continuous-compliance/" id="https://www.dbi-services.com/blog/data-anonymization-as-a-service-with-delphix-continuous-compliance/">a previous post</a></li>
</ul>



<h2 class="wp-block-heading" id="h-ownership-gaps-the-security-no-man-s-land">Ownership Gaps: The Security No Man&#8217;s Land</h2>



<p>We are shifting from a technical challenge to a human and organizational one. The security landscape moves so fast that the struggle of mastering every layer has become overwhelming.</p>



<p>This complexity is where governance goes to die. Infrastructure teams build the walls, developers write the code, and DBAs manage the house, but the accountability for the data itself often falls through the cracks. The most dangerous gap isn&#8217;t a missing feature; it’s the absence of a governance model strong enough to stop the game of hot potato and force a cross-domain ownership of security.</p>



<p>The CISO&#8217;s role in this landscape is not to master every technical layer, it is to force the question of ownership into the open. Who signs off on what data enters a non-production environment? Who is accountable when a dev database is restored without encryption? Who audits that masking policies are still effective after a release?</p>



<p>Without explicit answers to these questions, security becomes a game of assumptions. Every team assumes another layer is holding. And the gaps compound silently, until they don&#8217;t.</p>



<h2 class="wp-block-heading">From Handcrafted Scripts to Enterprise Platforms</h2>



<p>Every technique in this table can be implemented on a spectrum, from a carefully written script to a fully automated enterprise solution. The right choice depends on your scale, your team, and how much operational overhead you can realistically absorb.</p>



<ul class="wp-block-list">
<li><strong>TLS certificate deployment:</strong> you can generate and rotate certificates manually, instance by instance. Or you can automate the entire lifecycle using <strong><span style="text-decoration: underline">Ansible</span></strong> against an internal PKI with a consistent and auditable way that is invisible to the teams consuming it. The security outcome is identical; the operational cost is not.</li>



<li><strong>Data anonymization:</strong> a custom script that detects <a href="https://www.cloudflare.com/learning/privacy/what-is-pii/">PII </a>columns and replaces values with masked data works well at small scale. The challenge appears when your data spans multiple database engines (SQL Server, Oracle, PostgreSQL, &#8230;) and when anonymized values need to remain consistent across foreign keys and referential constraints. Replacing a customer ID in one table while leaving it intact in another isn&#8217;t anonymization, it&#8217;s a GDPR incident waiting to happen. Solutions like <a href="https://help.delphix.com/cc/current/content/continuous_compliance_home.htm">Delphix Continuous Compliance</a> handle cross-DBMS consistency, constraint awareness, and sensitive field detection out of the box, turning a fragile hand-rolled process into a governed, repeatable and auditable one.</li>



<li><strong>Dynamic masking and row-level security:</strong> defining a handful of policies manually in SSMS is perfectly reasonable for a contained environment. Automating policy deployment across environments and instances is a different challenge entirely. It is a level of scale where ad-hoc scripts quickly become a liability.</li>
</ul>



<h2 class="wp-block-heading" id="h-conclusion-moving-beyond-security-by-accident">Conclusion: Moving Beyond Security by Accident</h2>



<p>Security is not a one-time project. It is an operational discipline that requires the same rigor in a developer&#8217;s sandbox as it does in production, and that rigor has to be enforced <span style="text-decoration: underline"><strong>by design</strong></span>, not by goodwill.</p>



<p>Most breaches in non-production environments don&#8217;t happen because a tool failed. They happen because nobody owned the decision to use it in the first place.</p>



<p>At <strong>dbi services</strong>, we help organizations move from fragile, handcrafted scripts to governed, auditable architectures across every environment, every database engine, and every team. </p>



<p><strong>Because under GDPR, <span style="text-decoration: underline">one</span> incident is all it takes to make ownership everyone&#8217;s problem.</strong></p>
<p>L’article <a href="https://www.dbi-services.com/blog/tde-tls-data-security-governance-gap-in-lower-environments/">Beyond TDE and TLS: Bridging the Data Security Governance Gap in Lower Environments</a> est apparu en premier sur <a href="https://www.dbi-services.com/blog">dbi Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dbi-services.com/blog/tde-tls-data-security-governance-gap-in-lower-environments/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Remove grant to public in Oracle databases</title>
		<link>https://www.dbi-services.com/blog/remove-grant-to-public-in-oracle-databases/</link>
					<comments>https://www.dbi-services.com/blog/remove-grant-to-public-in-oracle-databases/#respond</comments>
		
		<dc:creator><![CDATA[Martin Bracher]]></dc:creator>
		<pubDate>Mon, 16 Mar 2026 14:18:48 +0000</pubDate>
				<category><![CDATA[Database Administration & Monitoring]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Security]]></category>
		<guid isPermaLink="false">https://www.dbi-services.com/blog/?p=40309</guid>

					<description><![CDATA[<p>CIS recommendations The Center for Internet Security publishes the &#8220;CIS Oracle database 19c Benchmark&#8221; with recommendations to enhance the security of Oracle databases. One type of recommendations is to remove grant execute to public (chapter 5.1.1.1-5.1.1.7 Public Privileges). There is a list of powerful SYS packages. And for security reasons, only users that really need [&#8230;]</p>
<p>L’article <a href="https://www.dbi-services.com/blog/remove-grant-to-public-in-oracle-databases/">Remove grant to public in Oracle databases</a> est apparu en premier sur <a href="https://www.dbi-services.com/blog">dbi Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading" id="h-cis-recommendations">CIS recommendations</h2>



<p>The <a href="https://en.wikipedia.org/wiki/Center_for_Internet_Security">Center for Internet Security</a> publishes the &#8220;CIS Oracle database 19c Benchmark&#8221; with recommendations to enhance the security of Oracle databases.</p>



<p>One type of recommendations is to remove grant execute to public (chapter 5.1.1.1-5.1.1.7 Public Privileges). There is a list of powerful SYS packages. And for security reasons, only users that really need this functionality should have access to it. But per default, it is granted to public and all users can use it.</p>



<p>In theory, to fix that is easy, e.g.</p>



<pre class="wp-block-code"><code>REVOKE EXECUTE ON DBMS_LDAP FROM PUBLIC;</code></pre>



<p>But is that really a good idea?</p>



<h2 class="wp-block-heading" id="h-who-is-using-an-object-from-another-schema">Who is using an object from another schema?</h2>



<p>If the object is used in a program unit, a named PL/SQL block (package, function, procedure, trigger), you can see the dependency in the view dba_dependencies.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
select distinct owner from dba_dependencies 
where referenced_name=&#039;DBMS_LDAP&#039; and owner&lt;&gt;&#039;SYS&#039;
order by 2,1;
</pre></div>


<p>And for these objects, the users already have a direct grant for it. So, remove of the public grant does not affect these user-objects.<br>But wait! Rarely used, but there are named blocks with invokers right&#8217;s (<code>create procedure procname AUTHID CURRENT_USER is</code>&#8230;) . See <a href="https://docs.oracle.com/cd/E29597_01/network.1111/e16543/authorization.htm" id="https://docs.oracle.com/cd/E29597_01/network.1111/e16543/authorization.htm">How Roles Work in PL/SQL Blocks</a></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
select owner, object_name from dba_procedures where authid=&#039;CURRENT_USER&#039;;
</pre></div>


<p>In this case the user can also access objects used in program units he has granted via a role. You have to check which users have access to these program units. These users are potentially affected by the change!</p>



<p>For objects used outside of above program units: If a user has a direct grant, or an indirect grant via a role to the object, removing the grant to public does not affect the work of this user with these objects.</p>



<p>So, what about the other users without direct/indirect grants to the object (except &#8220;public&#8221;)? How can we see if above mentioned objects are used (e.g. from external code in a Perl script or an application server connecting to the database)?</p>



<p>To see the usage of an object, we can use unified auditing and create an audit policy for the object.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
create audit policy CIS_CHECK_USAGE
actions
execute on sys.dbms_ldap
when &#039;SYS_CONTEXT(&#039;&#039;USERENV&#039;&#039;, &#039;&#039;CURRENT_USER&#039;&#039;) != &#039;&#039;SYS&#039;&#039;&#039; EVALUATE PER STATEMENT;

audit policy CIS_CHECK_USAGE;
alter audit policy cis_check_usage add actions EXECUTE on SYS.DBMS_LOB;
alter audit policy cis_check_usage add actions ...
</pre></div>


<p>Hint: Unified auditing can also be used if the Oracle binary is not relinked for unified audit (the relink only deactivates traditional auditing, unified auditing is always active)</p>



<p>To automate above steps, you can do it dynamically with the Perl script below (run it with $ORACLE_HOME/perl/bin/perl, so the required Oracle modules are present):</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: perl; title: ; notranslate">
  use DBI;
  my $dbh = DBI-&gt;connect(&#039;dbi:Oracle:&#039;, &#039;&#039;, &#039;&#039;,{ PrintError =&gt; 1, ora_session_mode=&gt;2 });
  my @pdblist;
  my $sth=$dbh-&gt;prepare(q{select PDB_NAME from cdb_pdbs where pdb_name&lt;&gt;&#039;PDB$SEED&#039; union select &#039;CDB$ROOT&#039; from dual});
  $sth-&gt;execute();
  while (my @row = $sth-&gt;fetchrow_array) {
    push(@pdblist, $row&#x5B;0]);
  }

  foreach my $pdb (@pdblist){
    # switch PDB
    print &quot;PDB=$pdb\n&quot;;
    $dbh-&gt;do(&quot;alter session set container=$pdb&quot;);

    # create cis_check_usage
    print q{ create audit policy cis_check_usage actions all on sys.AUD$ when &#039;SYS_CONTEXT(&#039;&#039;USERENV&#039;&#039;, &#039;&#039;CURRENT_USER&#039;&#039;) != &#039;&#039;SYS&#039;&#039;&#039; EVALUATE PER STATEMENT}.&quot;\n&quot;;
    $dbh-&gt;do(q{ create audit policy cis_check_usage actions all on sys.AUD$ when &#039;SYS_CONTEXT(&#039;&#039;USERENV&#039;&#039;, &#039;&#039;CURRENT_USER&#039;&#039;) != &#039;&#039;SYS&#039;&#039;&#039; EVALUATE PER STATEMENT});
    $dbh-&gt;do(q{ audit policy cis_check_usage});

    # add execute to public
    my $sql=q{
     SELECT  PRIVILEGE||&#039; on &#039;||owner||&#039;.&#039;||table_name FROM DBA_TAB_PRIVS WHERE GRANTEE=&#039;PUBLIC&#039; AND PRIVILEGE=&#039;EXECUTE&#039; AND TABLE_NAME IN (
     &#039;DBMS_LDAP&#039;,&#039;UTL_INADDR&#039;,&#039;UTL_TCP&#039;,&#039;UTL_MAIL&#039;,&#039;UTL_SMTP&#039;,&#039;UTL_DBWS&#039;,&#039;UTL_ORAMTS&#039;,&#039;UTL_HTTP&#039;,&#039;HTTPURITYPE&#039;,
     &#039;DBMS_ADVISOR&#039;,&#039;DBMS_LOB&#039;,&#039;UTL_FILE&#039;,
     &#039;DBMS_CRYPTO&#039;,&#039;DBMS_OBFUSCATION_TOOLKIT&#039;, &#039;DBMS_RANDOM&#039;,
     &#039;DBMS_JAVA&#039;,&#039;DBMS_JAVA_TEST&#039;,
     &#039;DBMS_SCHEDULER&#039;,&#039;DBMS_JOB&#039;,
     &#039;DBMS_SQL&#039;, &#039;DBMS_XMLGEN&#039;, &#039;DBMS_XMLQUERY&#039;,&#039;DBMS_XMLSTORE&#039;,&#039;DBMS_XMLSAVE&#039;,&#039;DBMS_AW&#039;,&#039;OWA_UTIL&#039;,&#039;DBMS_REDACT&#039;,
     &#039;DBMS_CREDENTIAL&#039;
      )};
    $sth=$dbh-&gt;prepare(&quot;$sql&quot;);
    $sth-&gt;execute();
    while (my @result = $sth-&gt;fetchrow_array) {
      print  &quot;alter audit policy cis_check_usage add actions $result&#x5B;0]\n&quot;;
      $dbh-&gt;do(&quot;alter audit policy cis_check_usage add actions $result&#x5B;0]&quot;);
    }
  }

</pre></div>


<h2 class="wp-block-heading" id="h-revoke-the-grants">Revoke the grants</h2>



<p>After some days/weeks, you can evaluate the usage of dbms_ldap or other objects audited by the cis_check_usage policy</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
select dbusername, current_user, object_schema||&#039;.&#039;||object_name as object, 
      sql_text, system_privilege_used,
       system_privilege, unified_audit_policies, con_id , event_timestamp 
from cdb_unified_audit_trail 
where unified_audit_policies like &#039;%CIS_CHECK_USAGE%&#039;;
</pre></div>


<p>With this query, we see the usage of the objects we audited with the CIS_CHECK_USAGE policy. If there are no rows, check if you really enabled the policy (<code>select * from audit_unified_enabled_policies where policy_name='CIS_CHECK_USAGE';</code>)</p>



<p>With the next query, we exclude the objects per user that can be accessed by a direct grant or a grant via a role, so, a revoke from public will not affect this user.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
select distinct current_user, action_name, object_schema, object_name, con_id 
from cdb_unified_audit_trail a
where unified_audit_policies like &#039;%CIS_CHECK_USAGE%&#039;
and current_user not in ( 
  select grantee from cdb_tab_privs -- direct grant
  where owner=a.object_schema and table_name=a.object_name and con_id=a.con_id
union all
  select r.grantee from cdb_role_privs r, cdb_tab_privs t -- grant via role
  where r.granted_role=t.grantee and r.con_id=t.con_id 
  and r.grantee=a.current_user   and t.owner=a.object_schema 
  and t.table_name=a.object_name and r.con_id=a.con_id
);
</pre></div>


<p>And what is left, needs attention.</p>



<p>Sometimes the objects are used by a background process, e.g. if you see the object_name DBMS_SQL, but  in sql_text it is not used, then the user probably does not need it. But if it is present in sql_text, then the user definitely needs a grant. I recommend to grant the object via a role, so it behaves as before, the user can use it directly, but not in procedures/functions/packages.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
create  role cis_dbms_sql ;
grant execute on sys.dbms_sql to cis_dbms_sql;
grant cis_dbms_sql to user1;
</pre></div>


<p>Then pragmatically, remove the execute rights from public on a test system and check if the application still works as expected. Generate the revoke commands dynamically, and do not forget to also dynamically generate an undo script in case of problems:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
SELECT  &#039;revoke &#039;||PRIVILEGE||&#039; on &#039;||owner||&#039;.&#039;||table_name||&#039; from PUBLIC;&#039; 
FROM DBA_TAB_PRIVS 
WHERE GRANTEE=&#039;PUBLIC&#039; AND PRIVILEGE=&#039;EXECUTE&#039; AND TABLE_NAME IN (
   &#039;DBMS_LDAP&#039;,&#039; UTL_INADDR&#039; ,&#039;UTL_TCP&#039;, &#039;UTL_MAIL&#039;, &#039;UTL_SMTP&#039;, &#039;UTL_DBWS&#039;,
 &#039;UTL_ORAMTS&#039;,&#039;UTL_HTTP&#039;,&#039;HTTPURITYPE&#039;,
&#039;DBMS_ADVISOR&#039;,&#039;DBMS_LOB&#039;,&#039;UTL_FILE&#039;,
&#039;DBMS_CRYPTO&#039;,&#039;DBMS_OBFUSCATION_TOOLKIT&#039;, &#039;DBMS_RANDOM&#039;,
&#039;DBMS_JAVA&#039;,&#039;DBMS_JAVA_TEST&#039;,
&#039;DBMS_SCHEDULER&#039;,&#039;DBMS_JOB&#039;,
&#039;DBMS_SQL&#039;, &#039;DBMS_XMLGEN&#039;, &#039;DBMS_XMLQUERY&#039;,&#039;DBMS_XMLSTORE&#039;,&#039;DBMS_XMLSAVE&#039;,&#039;DBMS_AW&#039;,&#039;OWA_UTIL&#039;,&#039;DBMS_REDACT&#039;,
&#039;DBMS_CREDENTIAL&#039;
);

SELECT  &#039;grant &#039;||PRIVILEGE||&#039; on &#039;||owner||&#039;.&#039;||table_name||&#039; to PUBLIC;&#039;
FROM DBA_TAB_PRIVS 
WHERE GRANTEE=&#039;PUBLIC&#039; AND PRIVILEGE=&#039;EXECUTE&#039; AND TABLE_NAME IN (
   &#039;DBMS_LDAP&#039;,&#039; UTL_INADDR&#039; ,&#039;UTL_TCP&#039;, &#039;UTL_MAIL&#039;, &#039;UTL_SMTP&#039;, &#039;UTL_DBWS&#039;,
 &#039;UTL_ORAMTS&#039;,&#039;UTL_HTTP&#039;,&#039;HTTPURITYPE&#039;,
&#039;DBMS_ADVISOR&#039;,&#039;DBMS_LOB&#039;,&#039;UTL_FILE&#039;,
&#039;DBMS_CRYPTO&#039;,&#039;DBMS_OBFUSCATION_TOOLKIT&#039;, &#039;DBMS_RANDOM&#039;,
&#039;DBMS_JAVA&#039;,&#039;DBMS_JAVA_TEST&#039;,
&#039;DBMS_SCHEDULER&#039;,&#039;DBMS_JOB&#039;,
&#039;DBMS_SQL&#039;, &#039;DBMS_XMLGEN&#039;, &#039;DBMS_XMLQUERY&#039;,&#039;DBMS_XMLSTORE&#039;,&#039;DBMS_XMLSAVE&#039;,&#039;DBMS_AW&#039;,&#039;OWA_UTIL&#039;,&#039;DBMS_REDACT&#039;,
&#039;DBMS_CREDENTIAL&#039;
);
</pre></div>


<p>It has to be run in each PDB and CDB$ROOT.</p>



<p>If all works as expected, then it is fine.</p>



<h2 class="wp-block-heading" id="h-installation-of-patches-and-new-components">Installation of patches and new components</h2>



<p>But keep that in mind if you want to install something later. It may fail. For example, install an rman catalog:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
RMAN&gt; create catalog;
create catalog;
error creating dbms_rcvcat package body
RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-06433: error installing recovery catalog
RMAN Client Diagnostic Trace file : /u01/app/oracle/diag/clients/user_oracle/RMAN_1732619876_110/trace/ora_rman_635844_0.trc
</pre></div>


<p>To create a valid rman catalog, you need to grant the execute right for UTL_HTTP, DBMS_LOB, DBMS_XMLGEN and DBMS_SQL directly to the rman user. Strange for me: it does not work if you grant it to a role (e.g. recovery_catalog_owner), but it works with a grant to public.</p>



<p>My recommendation to install new softare or patches is:</p>



<ul class="wp-block-list">
<li>Run the undo-script mentioned above (grant execute to public)</li>



<li>Apply the Oracle or application patch or new application installation</li>



<li>Check for invalid objects</li>



<li>Run the hardening-script (revoke execute from public)</li>



<li>Check for additional invalid objects and determine the missing grants</li>



<li>Extend your hardening script with the required grants and re-run it.</li>
</ul>



<h2 class="wp-block-heading" id="h-conclusion">Conclusion</h2>



<p>Generally, the CIS hardening about revoking execute from public is possible. But it is very dangerous that the functionality of the application could be compromised. Especially with components that are used very rarely, this could only be noticed very late at best, e.g. in the case of end-of-year processing.</p>
<p>L’article <a href="https://www.dbi-services.com/blog/remove-grant-to-public-in-oracle-databases/">Remove grant to public in Oracle databases</a> est apparu en premier sur <a href="https://www.dbi-services.com/blog">dbi Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dbi-services.com/blog/remove-grant-to-public-in-oracle-databases/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>SQL Server Always-On: Centralizing Backup History Across Replicas</title>
		<link>https://www.dbi-services.com/blog/sql-server-always-on-centralizing-backup-history-across-replicas/</link>
					<comments>https://www.dbi-services.com/blog/sql-server-always-on-centralizing-backup-history-across-replicas/#respond</comments>
		
		<dc:creator><![CDATA[Louis Tochon]]></dc:creator>
		<pubDate>Thu, 08 Jan 2026 17:19:10 +0000</pubDate>
				<category><![CDATA[Database Administration & Monitoring]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[AlwaysOn]]></category>
		<category><![CDATA[Backup]]></category>
		<guid isPermaLink="false">https://www.dbi-services.com/blog/?p=42169</guid>

					<description><![CDATA[<p>Replace brittle T-SQL links and manual checks with a central PowerShell orchestrator to reliably manage Always On backup data at scale.</p>
<p>L’article <a href="https://www.dbi-services.com/blog/sql-server-always-on-centralizing-backup-history-across-replicas/">SQL Server Always-On: Centralizing Backup History Across Replicas</a> est apparu en premier sur <a href="https://www.dbi-services.com/blog">dbi Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading" id="h-context">Context</h2>



<p>Monitoring backups in a SQL Server Always On Availability Group can often feel like a game of hide and seek where the rules change every time you flip a failover switch. On paper, your backup strategy is solid ; you’ve configured your replica priorities and your jobs are running like clockwork. But when you query the backup history to ensure everything is under control, you realize the truth is fragmented.</p>



<p>Because the <code><strong>msdb</strong></code> database is local to each instance, each replica only knows about the backups it performed itself. If your backups happen on the secondary today and the primary tomorrow, no single node holds the complete story. This leads to inconsistent monitoring reports, &#8220;false positive&#8221; alerts, and a lot of manual jumping between instances just to answer a simple question: <em>&#8220;Are we actually protected with consistent backups?&#8221;</em>.</p>



<p>Before we dive deeper, a quick disclaimer for the lucky ones: If you are running SQL Server 2022 and have implemented <em><strong><a href="https://learn.microsoft.com/en-us/sql/database-engine/availability-groups/windows/contained-availability-groups-overview?view=sql-server-ver17">Contained Availability Groups</a></strong></em> you can stop reading here, you are safe. In a Contained AG, the system databases are replicated alongside your data, meaning the backup history is finally unified and follows the group. </p>



<p>For the others, in this post, we’re going to explore how to stop chasing metadata across your cluster. We’ll look at the limitations of the local <code><strong>msdb</strong></code>, compare different ways to consolidate a unified backup view using <em>Linked Servers</em>, <em>OPENDATASOURCE</em>, and PowerShell, and see how to build a monitoring query that finally tells the whole truth, regardless of where the backup actually ran.</p>



<h2 class="wp-block-heading" id="h-the-traditional-approach">The traditional approach</h2>



<p>The traditional approach is therefore to query the <code>msdb</code> through the AG listener, pointing to the primary replica. Using a simple TSQL query to find the most recent backup, we get the following results.</p>



<pre class="wp-block-code"><code>SELECT
bs.database_name,
MAX(bs.backup_finish_date) AS LastBackup
FROM msdb.dbo.backupset bs
WHERE bs.database_name = 'StackOverflow2010'
GROUP BY bs.database_name;</code></pre>



<figure class="wp-block-image size-full is-resized"><img decoding="async" width="432" height="62" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/12/image-32.png" alt="" class="wp-image-42173" style="aspect-ratio:6.969246281825057;width:412px;height:auto" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/12/image-32.png 432w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/12/image-32-300x43.png 300w" sizes="(max-width: 432px) 100vw, 432px" /></figure>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="420" height="62" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/12/image-30.png" alt="" class="wp-image-42171" style="aspect-ratio:6.775901184774389;width:406px;height:auto" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/12/image-30.png 420w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/12/image-30-300x44.png 300w" sizes="auto, (max-width: 420px) 100vw, 420px" /></figure>



<p>As we can see, the two backup dates differ (14:39 being the time the database was created in the AG and 15:15 being the time of the last backup). As a result, if a failover occurs, the main <code>msdb</code> will contain incomplete data because the primary <code>msdb</code> will be the one on <em>SQLAGVM2</em>.</p>



<p>This traditional approach is perfectly acceptable for standalone instances because there is only one source of truth, but in the case of Always-On, we need a more robust solution. Let&#8217;s examine the different possibilities.</p>



<h2 class="wp-block-heading" id="h-the-good-old-linked-servers">The good old Linked Servers</h2>



<p>If you want to keep everything within the SQL Engine, Linked Servers are your go-to tool. The idea is simple: from your Primary replica, you reach out to the Secondary, query its <code>msdb</code>, and union the results with your local data. </p>



<pre class="wp-block-code"><code>SELECT
@@SERVERNAME AS &#091;PrimaryServer],
bs.database_name,
MAX(bs.backup_finish_date) AS LastBackup
FROM msdb.dbo.backupset bs
WHERE bs.database_name = 'StackOverflow2010'
GROUP BY bs.database_name

UNION ALL

SELECT
<strong>'REMOTE_MSDB'</strong> AS &#091;ReportingServer],
bs.database_name,
MAX(bs.backup_finish_date) AS LastBackup
FROM <strong>&#091;REMOTE_MSDB]</strong>.msdb.dbo.backupset bs
WHERE bs.database_name = 'StackOverflow2010'
GROUP BY bs.database_name;</code></pre>



<p>On paper, the best way to secure a Linked Server is to use the <strong><em><a href="https://learn.microsoft.com/en-us/sql/relational-databases/linked-servers/create-linked-servers-sql-server-database-engine?view=sql-server-ver17">Self </a></em></strong>option, ensuring that your own permissions are carried over to the next node. It’s the most transparent approach for auditing and security. However, this is where we often hit a silent wall: the <strong><a href="https://techcommunity.microsoft.com/blog/askds/understanding-kerberos-double-hop/395463">Double-Hop</a></strong>. Unless Kerberos delegation is perfectly configured in your domain, NTLM will prevent your identity from traveling to the second replica. You’ll end up with a connection error, not because of a lack of permissions, but because your identity simply couldn&#8217;t make the trip. To determine the type of authentication protocol you are using, use the following query.</p>



<pre class="wp-block-code"><code>SELECT auth_scheme 
FROM sys.dm_exec_connections 
WHERE session_id = @@SPID;</code></pre>



<p>To bypass this hurdle, it is common to see <strong><em>Fixed Logins</em></strong> being used as a pragmatic workaround. But by hardcoding credentials to make the bridge work, we create a permanent, pre-authenticated tunnel. From a security standpoint, this can facilitate <a href="https://www.crowdstrike.com/en-us/cybersecurity-101/cyberattacks/lateral-movement/">lateral movement</a> if one instance is ever compromised, a major concern in modern <strong>Zero Trust</strong> architectures. Furthermore, it obscures your audit logs, as the remote server only sees the service account instead of the actual user. These hidden complexities and security risks are precisely why many DBAs are now moving toward more decoupled, scalable alternatives.</p>



<h2 class="wp-block-heading" id="h-the-on-the-fly-connection-opendatasource">The &#8220;On-the-Fly&#8221; Connection: OPENDATASOURCE</h2>



<p>To address the frustrations of Linked Servers, another T-SQL path often explored is the use of <em>ad hoc </em>queries via <strong><em><a href="https://learn.microsoft.com/en-us/sql/t-sql/functions/opendatasource-transact-sql?view=sql-server-ver17">OPENDATASOURCE</a></em></strong>.<br>The concept is tempting: instead of building a permanent bridge (Linked Server), you use a temporary ladder ; <code>OPENDATASOURCE</code> allows you to define a connection string directly inside your T-SQL statement, reaching out to a remote replica only for the duration of that specific query. It feels lightweight and dynamic because it requires no pre-configured server objects.</p>



<p>In theory, you would use it like this to pull backup history from your secondary node:</p>



<pre class="wp-block-code"><code>SELECT 
    @@SERVERNAME AS &#091;Source Server],
    bs.database_name, 
    MAX(bs.backup_finish_date) AS LastBackup
FROM OPENDATASOURCE('MSOLEDBSQL', 'Data Source=SQLAGVM1,1432;Integrated Security=SSPI').msdb.dbo.backupset bs
WHERE bs.database_name = 'StackOverflow2010'
GROUP BY bs.database_name;</code></pre>



<p>However, if the environment is not properly configured, an error will occur immediately.</p>



<pre class="wp-block-code"><code>Msg 15281, Level 16, State 1, Line 1
SQL Server blocked access to STATEMENT 'OpenRowset/OpenDatasource' of component 'Ad Hoc Distributed Queries' because this component is turned off as part of the security configuration for this server. A system administrator can enable the use of 'Ad Hoc Distributed Queries' by using sp_configure. </code></pre>



<p>By default, SQL Server locks this door. It is a protective measure to prevent users from using the SQL instance as a jumping point to query any other server on the network. To get past this error, a sysadmin must explicitly enable <strong>Ad Hoc Distributed Queries</strong>. This requires tweaking the advanced configuration of the instance.</p>



<pre class="wp-block-code"><code>EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
GO
EXEC sp_configure 'Ad Hoc Distributed Queries', 1;
RECONFIGURE;
GO</code></pre>



<p>Once these options have been reconfigured, access to the remote <code>msdb</code> is finally possible.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="358" height="60" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/12/image-33.png" alt="" class="wp-image-42175" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/12/image-33.png 358w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/12/image-33-300x50.png 300w" sizes="auto, (max-width: 358px) 100vw, 358px" /></figure>



<p>While we successfully made <code>OPENDATASOURCE</code> work, the trade-offs are significant. We have ended up with a solution that is brittle, difficult to maintain, and a potential liability:</p>



<ul class="wp-block-list">
<li><strong>Hardcoding &amp; Maintenance:</strong> Every replica requires a manually adapted connection string. If a server is renamed, a port is migrated, or a password expires, the entire monitoring logic collapses.</li>



<li><strong>Security &amp; Shadow IT Risk:</strong> Enabling <em>Ad Hoc Distributed Queries</em> opens a permanent hole in your instance. You aren&#8217;t just allowing your script to run; you are allowing any sysadmin to connect to any external server, creating a <em>ghost </em>feature that can be easily misused.</li>
</ul>



<p>In short, we are fighting the SQL engine’s security defaults just to get a simple timestamp. For a truly robust and scalable solution, it is time to look beyond T-SQL.</p>



<h2 class="wp-block-heading" id="h-here-comes-the-superhero-powershell">Here comes the superhero Powershell</h2>



<p>PowerShell steps in as the ultimate lifesaver, delivering high-level automation and pure execution simplicity. It allows you to centralize and control your scripts from an external management server, piloting your entire fleet remotely without cluttering your SQL instances.</p>



<p>By leveraging the power of <strong><a href="https://dbatools.io/">dbatools</a></strong>, we shatter the limitations of traditional T-SQL. We gain dynamic flexibility and enhanced security by bypassing risky configurations, all while maintaining total control over how we manipulate the retrieved data. The security gain does not come from PowerShell itself, but from removing risky SQL Server surface area features and centralizing access control on a hardened management host. This works because PowerShell establishes <strong>direct connections</strong> from your management host to each replica. This bypasses the NTLM double-hop issue entirely, as your identity is never passed between servers, removing any need for complex Kerberos delegation or risky fixed logins.</p>



<p>Here is how to put this into practice. By using the Availability Group <strong>Listener</strong> as your unique gateway, you can dynamically discover the cluster topology and query all member nodes.</p>



<pre class="wp-block-code"><code>$Listener = 'SQLLISTENER,1432'
$TargetDB = 'StackOverflow2010'

try {
    $Nodes = Invoke-DbaQuery -SqlInstance $Listener -Database 'master' -Query "SELECT replica_server_name FROM sys.dm_hadr_availability_replica_cluster_states" 
    $BackupQuery = "SELECT SERVERPROPERTY('ServerName') as &#091;InstanceName], MAX(backup_finish_date) as &#091;LastBackup] FROM msdb.dbo.backupset WHERE database_name = '$TargetDB' GROUP BY database_name"
    write-output $Nodes
    $Results = foreach ($Node in $Nodes.replica_server_name) {
        write-output $Node
        Invoke-DbaQuery -SqlInstance $Node -Database 'msdb' -Query $BackupQuery -ErrorAction SilentlyContinue
    }

    $Results | Where-Object { $_.LastBackup } | Sort-Object LastBackup -Descending | Select-Object -First 1 | Format-Table -AutoSize
}
catch {
    Write-Error "Error : $($_.Exception.Message)"
}</code></pre>



<p>This script is just a first step, but it lays the foundation for truly scalable infrastructure management. By shifting the logic to PowerShell instead of overloading our SQL instances, we achieve a robust and extensible method capable of handling large Always-On ecosystems without additional manual effort.</p>



<p>In this example, the listener name is hardcoded for the sake of clarity. However, the true strength of this approach lies in its ability to work behind the scenes with a dynamic inventory. In a <strong>Production </strong>environment, you would typically query a <em>CMDB </em>or a centralized configuration file to automatically populate the list of instances. This transforms a simple check into a silent, reliable automation that adapts seamlessly as your SQL environment evolves.</p>



<p>While we wrote the T-SQL manually in this example for the sake of clarity, it is worth noting that <em>dbatools </em>offers an even more streamlined approach with the <code>Get-DbaBackupHistory</code> command. This native function eliminates the need for manual queries entirely, returning rich metadata objects that are ready to be filtered and aggregated across your entire fleet.</p>



<pre class="wp-block-code"><code>$Nodes.replica_server_name | Get-DbaBackupHistory -Database 'StackOverflow2010' | Sort-Object End -Descending | Select-Object -First 1</code></pre>



<h2 class="wp-block-heading" id="h-final-thoughts-taking-control-of-the-always-on-fleet">Final Thoughts: Taking Control of the Always-On Fleet</h2>



<p>To wrap up, remember that technical skills are only as good as the management strategy behind them. Transitioning away from legacy methods toward a PowerShell-driven approach is about gaining control over your environment. Here is what you should keep in mind:</p>



<ul class="wp-block-list">
<li><strong>Beyond T-SQL Boundaries:</strong> While <em>Linked Servers</em> or <em>OPENDATASOURCE</em> might work for quick fixes, they quickly become bottlenecks and security risks in hardened infrastructures.</li>



<li><strong>Object-Oriented Efficiency:</strong> By using PowerShell and <em>dbatools</em>, you stop managing raw text and start handling objects. This allows you to effortlessly filter, sort, and aggregate data from multiple Always-On nodes to extract a single, reliable source of truth.</li>



<li><strong>Smarter Security:</strong> Running queries externally via dedicated management shells ensures you maintain a high security posture without needing to enable high-risk surface area features on your SQL instances.</li>
</ul>



<p><strong>The real game-changer is the Central Management Server.</strong> By centralizing your logic on a dedicated administration machine, you stop scattering scripts across every instance. This server becomes your orchestrator: it pulls from your inventory (<em>CMDB</em>, central tables), broadcasts tasks across your entire fleet, and consolidates the results. This is exactly the approach we take at <strong>dbi services</strong> to manage the extensive SQL Server environments under our care. We leverage PowerShell and the <em>dbatools </em>module as the backbone of our scripting architecture. This allows us to collect data in the most comprehensive and optimized way possible, ensuring we deliver top-tier service to our clients.</p>



<p>This is how you move from artisanal, server-by-server management to an industrial-grade automation capable of piloting hundreds of instances with the same simplicity as a single one.</p>



<p></p>
<p>L’article <a href="https://www.dbi-services.com/blog/sql-server-always-on-centralizing-backup-history-across-replicas/">SQL Server Always-On: Centralizing Backup History Across Replicas</a> est apparu en premier sur <a href="https://www.dbi-services.com/blog">dbi Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dbi-services.com/blog/sql-server-always-on-centralizing-backup-history-across-replicas/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Data Anonymization as a Service with Delphix Continuous Compliance</title>
		<link>https://www.dbi-services.com/blog/data-anonymization-as-a-service-with-delphix-continuous-compliance/</link>
					<comments>https://www.dbi-services.com/blog/data-anonymization-as-a-service-with-delphix-continuous-compliance/#respond</comments>
		
		<dc:creator><![CDATA[Louis Tochon]]></dc:creator>
		<pubDate>Mon, 22 Dec 2025 10:43:15 +0000</pubDate>
				<category><![CDATA[Database management]]></category>
		<category><![CDATA[Delphix]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[anonymization]]></category>
		<category><![CDATA[compliance]]></category>
		<category><![CDATA[delphix]]></category>
		<category><![CDATA[GDPR]]></category>
		<guid isPermaLink="false">https://www.dbi-services.com/blog/?p=41856</guid>

					<description><![CDATA[<p>Context In the era of digital transformation, attack surfaces are constantly evolving and cyberattack techniques are becoming increasingly sophisticated. Maintaining the confidentiality, integrity, and availability of data is therefore a critical challenge for organizations, both from an operational and a regulatory standpoint (GDPR, ISO 27001, NIST). Therefore, data anonymization is crucial today. Contrary to a [&#8230;]</p>
<p>L’article <a href="https://www.dbi-services.com/blog/data-anonymization-as-a-service-with-delphix-continuous-compliance/">Data Anonymization as a Service with Delphix Continuous Compliance</a> est apparu en premier sur <a href="https://www.dbi-services.com/blog">dbi Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading" id="h-context">Context</h2>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<p>In the era of digital transformation, attack surfaces are constantly evolving and cyberattack techniques are becoming increasingly sophisticated. Maintaining the confidentiality, integrity, and availability of data is therefore a critical challenge for organizations, both from an operational and a regulatory standpoint (GDPR, ISO 27001, NIST). Therefore, data anonymization is crucial today.</p>



<p>Contrary to a widely held belief, the risk is not limited to the production environment. Development, testing, and pre-production environments are prime targets for attackers, as they often benefit from weaker security controls. The use of production data that is neither anonymized nor pseudonymized directly exposes organizations to data breaches, regulatory non-compliance, and legal sanctions.</p>
</div></div>
</div></div>



<h2 class="wp-block-heading" id="h-why-and-how-to-anonymize-data">Why and How to Anonymize Data</h2>



<p>Development teams require realistic datasets in order to:</p>



<ul class="wp-block-list">
<li>Test application performance</li>



<li>Validate complex business processes</li>



<li>Reproduce error scenarios</li>



<li>Train Business Intelligence or Machine Learning algorithms</li>
</ul>



<p>However, the use of real data requires the implementation of anonymization or pseudonymization mechanisms ensuring:</p>



<ul class="wp-block-list">
<li>Preservation of functional and referential consistency</li>



<li>Prevention of data subject re-identification</li>
</ul>



<p>Among the possible anonymization techniques, the main ones include:</p>



<ul class="wp-block-list">
<li><strong>Dynamic Data Masking</strong>, applied on-the-fly at access time but which does not anonymize data physically</li>



<li><strong>Tokenization</strong>, which replaces a value with a surrogate identifier</li>



<li><strong>Cryptographic hashing</strong>, with or without salting</li>
</ul>



<h2 class="wp-block-heading" id="h-direct-data-copy-from-production-to-development">Direct data copy from Production to Development</h2>



<p>In this scenario, a full backup of the production database is restored into a development environment. Anonymization is then applied using manually developed SQL scripts or ETL processes.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img loading="lazy" decoding="async" width="848" height="267" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/12/image-7.png" alt="" class="wp-image-41868" style="width:592px;height:auto" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/12/image-7.png 848w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/12/image-7-300x94.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/12/image-7-768x242.png 768w" sizes="auto, (max-width: 848px) 100vw, 848px" /></figure>
</div>


<p>This approach presents several critical weaknesses:</p>



<ul class="wp-block-list">
<li>Temporary exposure of personal data in clear text</li>



<li>Lack of formal traceability of anonymization processes</li>



<li>Risk of human error in scripts</li>



<li>Non-compliance with GDPR requirements</li>
</ul>



<p>This model should therefore be avoided in regulated environments.</p>



<h2 class="wp-block-heading" id="h-data-copy-via-a-staging-database-in-production">Data copy via a Staging Database in Production</h2>



<p>This model introduces an intermediate staging database located within a security perimeter equivalent to that of production. Anonymization is performed within this secure zone before replication to non-production environments.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img loading="lazy" decoding="async" width="887" height="337" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/12/image-8.png" alt="" class="wp-image-41869" style="width:621px;height:auto" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/12/image-8.png 887w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/12/image-8-300x114.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/12/image-8-768x292.png 768w" sizes="auto, (max-width: 887px) 100vw, 887px" /></figure>
</div>


<p>This approach makes it possible to:</p>



<ul class="wp-block-list">
<li>Ensure that no sensitive data in clear text leaves the secure perimeter</li>



<li>Centralize anonymization rules</li>



<li>Improve overall data governance</li>
</ul>



<p>However, several challenges remain:</p>



<ul class="wp-block-list">
<li>Versioning and auditability of transformation rules</li>



<li>Governance of responsibilities between teams (DBAs, security, business units)</li>



<li>Maintaining inter-table referential integrity</li>



<li>Performance management during large-scale anonymization</li>
</ul>



<h2 class="wp-block-heading" id="h-integration-of-delphix-continuous-compliance">Integration of Delphix Continuous Compliance</h2>



<p>In this architecture, <code><a href="https://cd.delphix.com/docs/latest/overview">Delphix</a></code> is integrated as the central engine for data virtualization and anonymization. The <em><a href="https://help.delphix.com/cc/">Continuous Compliance</a></em> module enables process industrialization through:</p>



<ul class="wp-block-list">
<li>An automated data profiler identifying sensitive fields</li>



<li>Deterministic or non-deterministic anonymization algorithms</li>



<li>Massively parallelized execution</li>



<li>Orchestration via REST APIs integrable into CI/CD pipelines</li>



<li>Full traceability of processing for audit purposes</li>
</ul>



<p>This approach enables the rapid provisioning of compliant, reproducible, and secure databases for all technical teams.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img loading="lazy" decoding="async" width="915" height="394" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/12/image-27.png" alt="" class="wp-image-42155" style="aspect-ratio:2.3224468636599274;width:653px;height:auto" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/12/image-27.png 915w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/12/image-27-300x129.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/12/image-27-768x331.png 768w" sizes="auto, (max-width: 915px) 100vw, 915px" /></figure>
</div>


<h2 class="wp-block-heading" id="h-conclusion">Conclusion</h2>



<p>Database anonymization should no longer be viewed as a one-time constraint but as a structuring process within the data lifecycle. It is based on three fundamental pillars:</p>



<ul class="wp-block-list">
<li>Governance</li>



<li>Pipeline industrialization</li>



<li>Regulatory compliance</li>
</ul>



<p>An in-house implementation is possible, but it requires a high level of organizational maturity, strong skills in anonymization algorithms, data engineering, and security, as well as a strict audit framework. Solutions such as Delphix provide an industrialized response to these challenges while reducing both operational and regulatory risks. </p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img loading="lazy" decoding="async" width="535" height="438" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/12/image-28.png" alt="" class="wp-image-42156" style="aspect-ratio:1.2215047625842816;width:388px;height:auto" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/12/image-28.png 535w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/12/image-28-300x246.png 300w" sizes="auto, (max-width: 535px) 100vw, 535px" /></figure>
</div>


<p>To take this further, Microsoft&#8217;s article explaining the integration of Delphix into Azure pipelines analyzes the same issues discussed above, but this time in the context of the cloud : <a href="https://learn.microsoft.com/en-us/azure/architecture/databases/guide/data-obfuscation-with-delphix-in-azure-data-factory">Use Delphix for Data Masking in Azure Data Factory and Azure Synapse Analytics</a></p>



<h2 class="wp-block-heading" id="h-what-s-next">What&#8217;s next ?</h2>



<p>This use case is just one example of how Delphix can be leveraged to optimize data management and compliance in complex environments. In upcoming articles, we will explore other recurring challenges, highlighting both possible in-house approaches and industrialized solutions with Delphix, to provide a broader technical perspective on data virtualization, security, and performance optimization.</p>



<h2 class="wp-block-heading" id="h-what-about-you">What about you ?</h2>



<p>How confident are you about the management of your confidential data? <br>If you have any doubts, please don’t hesitate to reach out to me to discuss them !</p>
<p>L’article <a href="https://www.dbi-services.com/blog/data-anonymization-as-a-service-with-delphix-continuous-compliance/">Data Anonymization as a Service with Delphix Continuous Compliance</a> est apparu en premier sur <a href="https://www.dbi-services.com/blog">dbi Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dbi-services.com/blog/data-anonymization-as-a-service-with-delphix-continuous-compliance/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Setting up TLS encryption and authentication in MongoDB</title>
		<link>https://www.dbi-services.com/blog/setting-up-tls-encryption-and-authentication-in-mongodb/</link>
					<comments>https://www.dbi-services.com/blog/setting-up-tls-encryption-and-authentication-in-mongodb/#respond</comments>
		
		<dc:creator><![CDATA[Julien Delattre]]></dc:creator>
		<pubDate>Mon, 10 Nov 2025 08:00:00 +0000</pubDate>
				<category><![CDATA[Database Administration & Monitoring]]></category>
		<category><![CDATA[Database management]]></category>
		<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Authentication]]></category>
		<category><![CDATA[authenticationdatabase]]></category>
		<category><![CDATA[Authorization]]></category>
		<category><![CDATA[encryption]]></category>
		<category><![CDATA[mongoservererror]]></category>
		<category><![CDATA[OpenSSL]]></category>
		<category><![CDATA[TLS]]></category>
		<category><![CDATA[tlscertificatekeyfile]]></category>
		<guid isPermaLink="false">https://www.dbi-services.com/blog/?p=38825</guid>

					<description><![CDATA[<p>When securing a MongoDB deployment, protecting sensitive data is paramount. MongoDB supports encryption throughout the lifecycle of the data, with three primary types of data encryption : Among these, encryption in transit is fundamental : it protects data as it moves between your application and the database. In MongoDB, this is achieved through TLS (Transport [&#8230;]</p>
<p>L’article <a href="https://www.dbi-services.com/blog/setting-up-tls-encryption-and-authentication-in-mongodb/">Setting up TLS encryption and authentication in MongoDB</a> est apparu en premier sur <a href="https://www.dbi-services.com/blog">dbi Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>When <strong>securing a MongoDB deployment</strong>, protecting sensitive data is paramount. MongoDB supports encryption <strong>throughout the lifecycle</strong> of the data, with three primary types of data encryption :</p>



<ul class="wp-block-list">
<li>Encryption <strong>in transit</strong></li>



<li>Encryption <strong>at rest</strong></li>



<li>Encryption <strong>in use</strong></li>
</ul>



<p><br>Among these, <strong>encryption in transit</strong> is fundamental : it protects data as it moves between your application and the database. In MongoDB, this is achieved through <strong>TLS (Transport Layer Security)</strong>, which ensures that communication remains private and secure. You have two options when it comes to using TLS for your database :</p>



<ul class="wp-block-list">
<li>Using TLS for <strong>encryption</strong> only.</li>



<li>Using TLS both for <strong>encryption</strong> and <strong>authentication</strong> to the database.</li>
</ul>



<p></p>



<h2 class="wp-block-heading" id="h-setting-up-tls-for-encryption">Setting up TLS for encryption</h2>



<h3 class="wp-block-heading" id="h-create-a-certificate-authority">Create a Certificate Authority</h3>



<p>We&#8217;ll first create a <strong>Certificate Authority</strong>. These certificates will be self-signed, which is fine for testing, but <strong>you shouldn&#8217;t use self-signed certificates in a production environment !</strong> On Linux, use the <code>openssl</code> library to generate the certificates.</p>



<pre class="wp-block-code"><code>openssl req -newkey rsa:4096 -nodes -x509 -days 365 -keyout ca.key -out ca.pem -subj "/C=CH/ST=ZH/L=Zurich/O=dbi/OU=MongoDBA/CN=vm.domain.com"</code></pre>



<p>Here is a description of some important parameters of the commands :</p>



<ul class="wp-block-list">
<li><code>-newkey rsa:4096</code> : Generates a new private key and a certificate request using RSA with a 4096-bit key size.</li>



<li><code>-nodes</code> : Skips password encryption of the private key. Without it, OpenSSL would prompt you to set a passphrase.</li>



<li><code>-x509</code> : Generates a self-signed certificate. <code>x509</code> is supported by MongoDB.</li>



<li><code>-days 365</code> : Validity of the certificate in days.</li>



<li><code>-keyout ca.key</code> : Filename for the private key.</li>



<li><code>-out ca.pem</code> : Filename for the certificate.</li>



<li><code>-subj "..."</code> : Provides the subject&#8217;s Distinguished Name (DN). If you don&#8217;t specify it, OpenSSL will prompt for each field.</li>
</ul>



<h3 class="wp-block-heading" id="h-create-a-server-certificate">Create a Server Certificate</h3>



<p>Then, we&#8217;ll create the server certificate for the MongoDB instance. In the <code>openssl-server.cnf</code> file below, you should change the <code>req_distinguished_name</code> fields with what you used while creating the Certificate Authority, and replace <code>vm.domain.com</code> by the name of your machine.</p>



<p>If you only have an IP and no DNS entry for your VM, use <code>IP.1</code> instead of <code>DNS.1</code> in the <code>alt_names</code> section.</p>



<pre class="wp-block-code"><code>cat &gt; openssl-server.cnf &lt;&lt;EOF
&#091; req ]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no

&#091; req_distinguished_name ]
C = CH
ST = ZH
L = Zurich
O = dbi
OU = MongoDBA
<strong>CN = myVM
</strong>
&#091; v3_req ]
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

&#091; alt_names ]
<strong>DNS.1 = myVM
</strong>EOF</code></pre>



<p>Then, generates the certificate with these commands :</p>



<pre class="wp-block-code"><code>openssl req -newkey rsa:4096 -nodes -keyout mongodb-server.key -out mongodb-server.csr -config openssl-server.cnf

openssl x509 -req -in mongodb-server.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out mongodb-server.crt -days 365 -extensions v3_req -extfile openssl-server.cnf

cat mongodb-server.key mongodb-server.crt &gt; mongodb-server.pem</code></pre>



<h3 class="wp-block-heading" id="h-create-a-client-certificate">Create a Client Certificate</h3>



<p>Finally, we&#8217;ll create a client certificate. The process is the same, with a few tweaks :</p>



<ul class="wp-block-list">
<li><code>OU</code> should be different from the one from the server certificate. It is not mandatory for the communication, but it will be for the authentication if you decide to enable it.</li>



<li><code>CN</code> should also be different.</li>



<li><code>extendedKeyUsage</code> should be set with <code>clientAuth</code> instead of <code>serverAuth</code>.</li>
</ul>



<pre class="wp-block-code"><code>cat &gt; openssl-client.cnf &lt;&lt;EOF
&#091; req ]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no

&#091; req_distinguished_name ]
C = CH
ST = ZH
L = Zurich
O = dbi
<strong>OU = MongoDBAClient
CN = userApp
</strong>
&#091; v3_req ]
keyUsage = digitalSignature, keyEncipherment
<strong>extendedKeyUsage = clientAuth
</strong>EOF</code></pre>



<p>The creation of the certificate is the same.</p>



<pre class="wp-block-code"><code>openssl req -newkey rsa:4096 -nodes -keyout mongodb-client.key -out mongodb-client.csr -config openssl-client.cnf

openssl x509 -req -in mongodb-client.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out mongodb-client.crt -days 365 -extensions v3_req -extfile openssl-client.cnf

cat mongodb-client.key mongodb-client.crt &gt; mongodb-client.pem</code></pre>



<h3 class="wp-block-heading" id="h-mongodb-configuration-change">MongoDB Configuration Change</h3>



<p>Make sure to set permissions correctly for your certificates.</p>



<pre class="wp-block-code"><code>chmod 600 ca.pem mongodb-server.pem mongodb-client.pem
chown mongod: ca.pem mongodb-server.pem mongodb-client.pem</code></pre>



<p>Now, you can change your MongoDB configuration file to include the certificates. Simply add the <code>net.tls</code> part to your <code>mongod.conf</code> file.</p>



<pre class="wp-block-code"><code>net:
  bindIp: yourIP
  port: 27017
  <strong>tls:
    mode: requireTLS
    certificateKeyFile: /path/to/mongodb-server.pem
    CAFile: /path/to/ca.pem</strong></code></pre>



<p>You can now restart your MongoDB instance with <code>systemctl restart mongod</code> (or whatever you&#8217;re using), and then try the connection to your instance for your client. Of course, the port mentioned in the <code>net.port</code> field of your configuration file shouldn&#8217;t be blocked by your firewall.</p>



<pre class="wp-block-code"><code>&gt; mongosh --host myVM --port 27017 --tls --tlsCertificateKeyFile mongodb-client.pem --tlsCAFile ca.pem
Current Mongosh Log ID:	682c9641bbe4593252ee7c8c
Connecting to:		mongodb://vmIP:27017/?directConnection=true&amp;tls=true&amp;tlsCertificateKeyFile=Fclient.pem&amp;tlsCAFile=ca.pem&amp;appName=mongosh+2.5.1
Using MongoDB:		8.0.9
Using Mongosh:		2.5.1

For mongosh info see: https://www.mongodb.com/docs/mongodb-shell/

test&gt;</code></pre>



<p>You&#8217;re now connected to your MongoDB instance through TLS ! And if you&#8217;re not using the certificate, the <code>requireTLS</code> mode prevents the connection from being established, and generated these error messages in your logs :</p>



<pre class="wp-block-code"><code>{"t":{"$date":"2025-05-21T04:43:55.277+00:00"},"s":"I",  "c":"EXECUTOR", "id":22988,   "ctx":"conn52","msg":"Error receiving request from client. Ending connection from remote","attr":{"error":{"code":141,"codeName":"SSLHandshakeFailed","errmsg":"<strong>The server is configured to only allow SSL connections</strong>"},"remote":"IP:50100","connectionId":52}}</code></pre>



<p><em>If you want to learn more about MongoDB logs, I wrote a blog on this topic: <a href="https://www.dbi-services.com/blog/mongodb-log-analysis-a-comprehensive-guide/">MongoDB Log Analysis : A Comprehensive Guide</a>.</em></p>



<h2 class="wp-block-heading" id="h-setting-up-tls-authentication">Setting up TLS authentication</h2>



<p>Now that you&#8217;re connected, we will set up authentication so that you can be connected as a specific user to MongoDB. Using the already established connection, create a user in the <code>$external</code> database. Each client certificate that you create can be mapped to one MongoDB user. Retrieve the username that you will use :</p>



<pre class="wp-block-code"><code>&gt; openssl x509 -in mongodb-client.pem -inform PEM -subject -nameopt RFC2253 | grep subject
subject=<strong>CN=userApp,OU=MongoDBA,O=dbi,L=Zurich,ST=ZH,C=CH</strong></code></pre>



<p>And then create the user in the <code>$external</code> database, using the existing MongoDB connection :</p>



<pre class="wp-block-code"><code>test&gt; db.getSiblingDB("$external").runCommand({
  createUser: "<strong>CN=userApp,OU=MongoDBA,O=dbi,L=Zurich,ST=ZH,C=CH</strong>",
  roles: &#091;
    { role: "userAdminAnyDatabase", db: "admin" }
  ]
});</code></pre>



<p>To check that everything works as intended, you can try to display collections in the <code>admin</code> database. For the moment, there is no error because you have all the rights to do it (no authorization is enforced).</p>



<pre class="wp-block-code"><code>test&gt; use admin
switched to db admin
admin&gt; show collections;
system.users
system.version</code></pre>



<p>You can now edit the MongoDB configuration file by adding the <code>net.tls.allowConnectionsWithoutCertificates</code> set to <code>true</code>, and the <code>security.authorization</code> flag set to <code>enabled</code>. The <code>mongod.conf</code> file should look like this :</p>



<pre class="wp-block-code"><code>net:
  bindIp: X.X.X.X
  port: XXXXX
  tls:
    mode: requireTLS
    certificateKeyFile: /path/to/mongodb-server.pem
    CAFile: /path/to/ca.pem
<strong>    allowConnectionsWithoutCertificates: false
</strong>
<strong>security:
  authorization: enabled</strong></code></pre>



<p>After restarting with <code>systemctl restart mongod</code>, you can now connect again. If you use the same command as before, you will log in without authentication, and get the error below whenever you try to do anything :</p>



<pre class="wp-block-code"><code>MongoServerError&#091;Unauthorized]: Command listCollections requires authentication</code></pre>



<p>So you should now connect via this command :</p>



<pre class="wp-block-code"><code>mongosh --host vmIP --port 27017 --tls --tlsCertificateKeyFile mongodb-client.pem --tlsCAFile ca.pem --authenticationDatabase '$external' --authenticationMechanism MONGODB-X509</code></pre>



<p>If you want to show the <code>admin</code> collections, you will now get an error, because your user only has the <code>userAdminAnyDatabase</code> role granted (this role was chosen during the user creation, see above).</p>



<pre class="wp-block-code"><code>admin&gt; show collections
MongoServerError&#091;Unauthorized]: not authorized on admin to execute command { listCollections: 1, filter: {}, cursor: {}, nameOnly: true, authorizedCollections: false, lsid: { id: UUID("9c48b4c4-7702-49ce-a97c-52763b2ad6b3") }, $db: "admin" }</code></pre>



<p>But it&#8217;s fine, you can grant yourself more roles (<code>readWriteAnyDatabase</code>, for instance) and create new users if you want.</p>



<p>The <strong>communication between the client and the server is now fully secured</strong>. Congratulations !</p>



<h4 class="wp-block-heading" id="h-mongoservererror-badvalue">MongoServerError[BadValue]</h4>



<p><em>Side note</em> : if you ever encounter this error:</p>



<pre class="wp-block-code"><code>MongoServerError&#091;BadValue]: Cannot create an x.509 user with a subjectname that would be recognized as an internal cluster member</code></pre>



<p>&#8230; make sure to follow the <a href="https://www.ietf.org/rfc/rfc2253.txt RFC-2253">RFC-2253</a> standards. For instance, you could have this error if one of the field is too long. Also, as a reminder, the client certificate should have a different Distinguished Name (DN) than the server certificate (see <a href="https://www.mongodb.com/docs/manual/core/security-x.509/">documentation</a> for more information).</p>



<p></p>
<p>L’article <a href="https://www.dbi-services.com/blog/setting-up-tls-encryption-and-authentication-in-mongodb/">Setting up TLS encryption and authentication in MongoDB</a> est apparu en premier sur <a href="https://www.dbi-services.com/blog">dbi Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dbi-services.com/blog/setting-up-tls-encryption-and-authentication-in-mongodb/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Scheduling OpenSCAP reports in SUSE Multi-Linux Manager</title>
		<link>https://www.dbi-services.com/blog/scheduling-openscap-reports-in-suse-multi-linux-manager/</link>
					<comments>https://www.dbi-services.com/blog/scheduling-openscap-reports-in-suse-multi-linux-manager/#respond</comments>
		
		<dc:creator><![CDATA[Daniel Westermann]]></dc:creator>
		<pubDate>Wed, 23 Jul 2025 14:44:32 +0000</pubDate>
				<category><![CDATA[Operating systems]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[SUSE]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[SUMA]]></category>
		<guid isPermaLink="false">https://www.dbi-services.com/blog/?p=39544</guid>

					<description><![CDATA[<p>As we&#8217;ve recently supported some customers on SUSE Multi Linux Manager I&#8217;d like share something which was not as easy to implement as it appeared to be in the first place. But first of all, what is SUSE Multi Linux Manager? It is basically a fork of Spacewalk which was also used as the upstream [&#8230;]</p>
<p>L’article <a href="https://www.dbi-services.com/blog/scheduling-openscap-reports-in-suse-multi-linux-manager/">Scheduling OpenSCAP reports in SUSE Multi-Linux Manager</a> est apparu en premier sur <a href="https://www.dbi-services.com/blog">dbi Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>As we&#8217;ve recently supported some customers on <a href="https://www.suse.com/products/multi-linux-manager/" target="_blank" rel="noreferrer noopener">SUSE Multi Linux Manager</a> I&#8217;d like share something which was not as easy to implement as it appeared to be in the first place. But first of all, what is SUSE Multi Linux Manager? It is basically a fork of <a href="https://spacewalkproject.github.io" target="_blank" rel="noreferrer noopener">Spacewalk</a> which was also used as the upstream project by the <a href="https://www.redhat.com/en/technologies/management/satellite" target="_blank" rel="noreferrer noopener">Red Hat Satellite</a> product. But as Spacewalk was dis-continued and the project on <a href="https://github.com/spacewalkproject/spacewalk" target="_blank" rel="noreferrer noopener">Github</a> was archived some people decided to fork in and started a new project called <a href="https://www.uyuni-project.org" target="_blank" rel="noreferrer noopener">Uyuni</a>, and this is now the upstream project for SUSE Multi Linux Manager. One of the great things about Uyuni and SUSE Multi Linux Manager is, that it supports various Linux distributions such as <a href="https://www.suse.com" target="_blank" rel="noreferrer noopener">SUSE</a> and <a href="https://www.opensuse.org" target="_blank" rel="noreferrer noopener">openSUSE</a> distributions, <a href="https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux">Red Hat</a>, <a href="https://rockylinux.org" target="_blank" rel="noreferrer noopener">Rocky</a>, <a href="https://www.oracle.com/linux/" target="_blank" rel="noreferrer noopener">Oracle</a> and <a href="https://almalinux.org" target="_blank" rel="noreferrer noopener">Alma</a> Linux, <a href="https://www.debian.org">Debian</a>, <a href="https://ubuntu.com">Ubuntu</a>, and also ancient versions of <a href="https://centos.org">CentOS</a> if you still depend on them.</p>



<p>I am not going into the setup or basic configuration as you can already find related bogs here and more information in the <a href="https://documentation.suse.com/suma/5.0/en/suse-manager/index.html" target="_blank" rel="noreferrer noopener">documentation</a>:</p>



<ul class="wp-block-list">
<li><a href="https://www.dbi-services.com/blog/uyuni-an-open-source-configuration-and-infrastructure-management-solution-for-software-defined-infrastructure-1-the-server/">Uyuni, an open-source configuration and infrastructure management solution for software-defined infrastructure (1) – The server</a> (this is for version 4.x)</li>



<li><a href="https://www.dbi-services.com/blog/uyuni-an-open-source-configuration-and-infrastructure-management-solution-for-software-defined-infrastructure-2-adding-a-client/">Uyuni, an open-source configuration and infrastructure management solution for software-defined infrastructure (2) – Adding a client</a> (this is for version 4.x)</li>



<li><a href="https://www.dbi-services.com/blog/suma-suse-manager-is-back-and-it-has-a-new-name-suse-multi-linux/" target="_blank" rel="noreferrer noopener">SUMA (SUSE Manager) is back and it has a new name: SUSE Multi-Linux</a></li>



<li><a href="https://www.dbi-services.com/blog/suse-manager-installation/" target="_blank" rel="noreferrer noopener">SUSE Manager installation</a> (this is for version 4)</li>
</ul>



<p>What I want to look at in this post is automatic scheduling of <a href="https://www.open-scap.org/tools/openscap-base/" target="_blank" rel="noreferrer noopener">OpenSCAP</a> scans/reports. When this requirement came up, it seemed pretty easy to do, as you can easily schedule such a scan against a single system. As you can see below I have a Red Hat 9 system registered to my SUSE Multi Linux Server:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="460" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_155945-1024x460.png" alt="" class="wp-image-39653" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_155945-1024x460.png 1024w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_155945-300x135.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_155945-768x345.png 768w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_155945-1536x690.png 1536w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_155945.png 1898w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>What you can easily do out of the box is to manually schedule an OpenSCAP scan:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="460" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160301-1024x460.png" alt="" class="wp-image-39654" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160301-1024x460.png 1024w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160301-300x135.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160301-768x345.png 768w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160301-1536x690.png 1536w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160301.png 1898w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Once the scan completes, it becomes visible under the &#8220;List Scan&#8221; tab and you can browse into the details:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="242" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160438-1-1024x242.png" alt="" class="wp-image-39655" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160438-1-1024x242.png 1024w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160438-1-300x71.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160438-1-768x181.png 768w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160438-1-1536x363.png 1536w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160438-1.png 1898w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="372" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160606-1024x372.png" alt="" class="wp-image-39656" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160606-1024x372.png 1024w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160606-300x109.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160606-768x279.png 768w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160606-1536x559.png 1536w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160606.png 1864w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="372" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160627-1024x372.png" alt="" class="wp-image-39657" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160627-1024x372.png 1024w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160627-300x109.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160627-768x279.png 768w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160627-1536x559.png 1536w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160627.png 1864w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Quite easy to do but still a manual action. As we wanted to have it automated the obvious choice was to create a &#8220;Recurring Action&#8221;:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="176" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160738-1024x176.png" alt="" class="wp-image-39658" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160738-1024x176.png 1024w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160738-300x52.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160738-768x132.png 768w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160738-1536x264.png 1536w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160738.png 1864w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>This gives you to option to create and configure a &#8220;Recurring Action&#8221;:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="410" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160933-1024x410.png" alt="" class="wp-image-39659" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160933-1024x410.png 1024w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160933-300x120.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160933-768x308.png 768w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160933-1536x616.png 1536w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_160933.png 1864w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The issue is, there is no pre-defined &#8220;Custom State&#8221; which is scheduling an OpenSCAP scan:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="350" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_161042-1024x350.png" alt="" class="wp-image-39660" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_161042-1024x350.png 1024w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_161042-300x103.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_161042-768x263.png 768w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_161042-1536x526.png 1536w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_161042.png 1864w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The very same is true for &#8220;System Groups&#8221;, which you normally would use because otherwise you&#8217;d need to schedule that on every single system:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="154" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_161201-1024x154.png" alt="" class="wp-image-39661" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_161201-1024x154.png 1024w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_161201-300x45.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_161201-768x116.png 768w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_161201-1536x232.png 1536w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_161201.png 1864w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The last option seemed to be something under &#8220;Schedule&#8221; but this only gives you a list of what you already have:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="376" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_161740-1-1024x376.png" alt="" class="wp-image-39662" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_161740-1-1024x376.png 1024w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_161740-1-300x110.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_161740-1-768x282.png 768w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_161740-1-1536x563.png 1536w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_161740-1.png 1870w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>At this point we were stuck and had to talk to SUSE support, which really was a great experience by the way. It turned out there is no easy, build-in, way to do this. A feature request has been logged, but of course there is no guarantee that it will be implemented. </p>



<p>But, there is a workaround, not a very beautiful one, but at least it works. SUSE Multi Linux Manager (and Uyuni of course) come with an <a href="https://documentation.suse.com/suma/5.0/api/suse-manager/index.html" target="_blank" rel="noreferrer noopener">API</a> and there is one call for triggering an <a href="https://documentation.suse.com/suma/5.0/api/suse-manager/api/system.scap.html" target="_blank" rel="noreferrer noopener">OpenSCAP scan</a>. Using this, a custom state channel can be created which in turn calls the API to trigger the scan:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="376" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_162705-1024x376.png" alt="" class="wp-image-39663" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_162705-1024x376.png 1024w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_162705-300x110.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_162705-768x282.png 768w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_162705-1536x563.png 1536w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_162705.png 1870w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="381" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_162934-1024x381.png" alt="" class="wp-image-39664" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_162934-1024x381.png 1024w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_162934-300x112.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_162934-768x286.png 768w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_162934-1536x572.png 1536w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_162934.png 1870w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The &#8220;SLS Contents&#8221; actually contains the code (Python in this case) which is taking to the API and triggers the scan:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; highlight: [14]; title: ; notranslate">
/usr/local/bin/schedule_xccdf_scan.py:
  file.managed:
    - user: root
    - group: root
    - mode: 755
    - contents: |
        #!/usr/bin/python3
        import xmlrpc.client

        client = xmlrpc.client.ServerProxy(&#039;https://suma.dwe.local/rpc/api&#039;)
        key = client.auth.login(&#039;admin&#039;, &#039;xxxx&#039;)
        client.system.scap.scheduleXccdfScan(
            key,
            1000010000,
            &#039;/usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml&#039;,
            &#039;--profile xccdf_org.ssgproject.content_profile_cis_server_l1&#039;
        )
        client.auth.logout(key)

schedule_xccdf_scan:
  cmd.run:
    - name: /usr/local/bin/schedule_xccdf_scan.py
    - require:
      - file: /usr/local/bin/schedule_xccdf_scan.py
</pre></div>


<p>I am not going into the code itself, this should be easy to understand. The important part is the system ID in line 14. This defines the system you want the scan to happen on (you can also provide an array of systems, see the API documentation linked above).</p>



<p>As soon as you have this, you can schedule this automatically as a recurring action on either the system itself, or a group of systems in &#8220;System Groups&#8221;:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="202" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_163519-1024x202.png" alt="" class="wp-image-39668" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_163519-1024x202.png 1024w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_163519-300x59.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_163519-768x152.png 768w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_163519-1536x303.png 1536w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_163519.png 1870w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="227" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_163558-1024x227.png" alt="" class="wp-image-39669" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_163558-1024x227.png 1024w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_163558-300x67.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_163558-768x170.png 768w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_163558-1536x341.png 1536w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_163558.png 1870w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="416" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_163655-1024x416.png" alt="" class="wp-image-39670" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_163655-1024x416.png 1024w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_163655-300x122.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_163655-768x312.png 768w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_163655-1536x624.png 1536w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/07/Screenshot_20250723_163655.png 1870w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Not as easy as it could be, and the systems are still hard coded in the Python code, but at least we have something that works. Hope that helps.</p>
<p>L’article <a href="https://www.dbi-services.com/blog/scheduling-openscap-reports-in-suse-multi-linux-manager/">Scheduling OpenSCAP reports in SUSE Multi-Linux Manager</a> est apparu en premier sur <a href="https://www.dbi-services.com/blog">dbi Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dbi-services.com/blog/scheduling-openscap-reports-in-suse-multi-linux-manager/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Different types of Oracle wallets</title>
		<link>https://www.dbi-services.com/blog/different-types-of-oracle-wallets/</link>
					<comments>https://www.dbi-services.com/blog/different-types-of-oracle-wallets/#respond</comments>
		
		<dc:creator><![CDATA[Martin Bracher]]></dc:creator>
		<pubDate>Tue, 20 May 2025 11:14:47 +0000</pubDate>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Security]]></category>
		<guid isPermaLink="false">https://www.dbi-services.com/blog/?p=38143</guid>

					<description><![CDATA[<p>In this blog post I will explain the different types of Oracle wallet with the auto_login feature. What is an Oracle Wallet An Oracle wallet is used to store certificates for Listeners with https protocol, or it can be used as an encrypted password store for Oracle logins. Technically, an Oracle wallet is an encrypted, [&#8230;]</p>
<p>L’article <a href="https://www.dbi-services.com/blog/different-types-of-oracle-wallets/">Different types of Oracle wallets</a> est apparu en premier sur <a href="https://www.dbi-services.com/blog">dbi Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>In this blog post I will explain the different types of Oracle wallet with the auto_login feature.</p>



<h2 class="wp-block-heading" id="h-what-is-an-oracle-wallet">What is an Oracle Wallet</h2>



<p>An Oracle wallet is used to store certificates for Listeners with https protocol, or it can be used as an encrypted password store for Oracle logins.</p>



<p>Technically, an Oracle wallet is an encrypted, password-protected <a href="https://en.wikipedia.org/wiki/PKCS_12">PKCS#12 container file</a> (<code>ewallet.p12</code>) that also can be accessed with <a href="https://docs.openssl.org/master/man1/openssl/">openssl tools</a> to show and extract keys and certificates. </p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
openssl pkcs12 -nokeys -info -in ewallet.p12
</pre></div>


<p>Storing credentials (user/password/tns_alias) in an Oracle wallet is a proprietary extension from Oracle which is not understood by openssl. </p>



<pre class="wp-block-code"><code>Secret bag
Bag attributes
    localKeyID: AA BB CC DD ....
Bag Type: 1.2.840.113549.1.16.12.12
Bag Value: <strong>&lt;Unsupported tag 16&gt;</strong></code></pre>



<p>Generally, <strong>do not</strong> modify an Oracle wallet with openssl tools! To work with Oracle wallets, use the <code>orapki</code> or <code>mkstore</code> utilities in $ORACLE_HOME/bin;</p>



<h2 class="wp-block-heading" id="h-auto-login-wallets">Auto-login Wallets</h2>



<p>The PKCS#12 file (<code>ewallet.p12</code>) is password protected. To startup SSL Listeners or to login with sqlplus or dgmgrl to a database non-interactive (without a password prompt), a different wallet-type is required, a so-called auto_login* wallet.</p>



<p>How does that work? Oracle creates a proprietary shadow-file of the <code>ewallet.p12</code> file, the <code>cwallet.sso</code>; Oracle tools like sqlplus or tnslsnr have access to this proprietary file without the need of a password. Security is primarily based on filesystem permissions and a blackbox file structure of the <code>cwallet.sso</code>. Not very secure, but even better than cleartext passwords in files.</p>



<p>For this auto-login feature, there are 3 additional wallet-types (2-4):</p>



<ol class="wp-block-list">
<li>The normal wallet without auto-login (ewallet.p12)</li>



<li>The <strong>auto_login</strong> wallet (ewallet.p12, cwallet.sso)</li>



<li>The <strong>auto_login_local</strong> wallet (ewallet.p12, cwallet.sso)</li>



<li>The <strong>auto_login_only</strong> wallet (cwallet.sso)</li>
</ol>



<p>To create the wallets, use the <code>orapki</code> command</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
orapki wallet create -wallet .  #create a wallet in the current directory (non-auto-login)
orapki wallet create -wallet .  -auto_login
orapki wallet create -wallet .  -auto_login_local
orapki wallet create -wallet .  -auto_login_only
</pre></div>


<h3 class="wp-block-heading" id="h-auto-login-only">auto_login_only</h3>



<p>The auto_login_only wallet is a special case. There is no PCKS#12 container, and you have access to the content without a wallet-password. So you can extract user-credentials in cleartext or private keys without a password! So do not use auto_login_only to store user-certificates/private-keys or credentials. This type of wallet is intended to only store trusted (public) certificates, required to initialize SSL connections to a remote site.</p>



<h3 class="wp-block-heading" id="h-auto-login-and-auto-login-local">auto_login and auto_login_local</h3>



<p>The auto_login and auto_login_local wallet contains both the <code>ewallet.p12</code> and the <code>cwallet.sso</code> file. To modify the wallet, the wallet password must be provided. <code>orapki</code> then updates both files.</p>



<p>The difference of the two wallet types are that the auto-login feature of the auto_login_local wallet can only be used on the host it was created and and by the user who created the wallet. But do not confuse: the <code>ewallet.p12</code> file can be accessed with the wallet password on other systems or by other users. The difference is in the <code>cwallet.sso</code> file.</p>



<p>The auto_login_local wallet should be used for server certificates (in orapki named user_certificate) The server certificate should not be used on another host.</p>



<h3 class="wp-block-heading" id="h-determine-the-wallet-type">Determine the wallet-type</h3>



<p>To see which wallet type is on a system, that is a bit tricky. Oracle tools will not show the wallet type. If there is only a <code>cwallet.sso</code>, but no <code>ewallet.p12</code> file, then it is probably an auto_login_only wallet. But: it is also possible that someone only copied the <code>cwallet.sso</code> file from another system. That works for auto-login, but you can no longer modify the wallet. To test, use <code>mkstore -wrl . -listCredential</code>; if it asks for a password, it is not an auto_login_only wallet. </p>



<p>And to see if it is a auto_login_local or auto_login (global) wallet you have to copy it to another host and see if the auto login feature still works or not.</p>



<p>But is there a better way than such try-and-error methods?</p>



<p>Yes! use the <code>od</code> (octal dump) utility and analyze the first line.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
od cwallet.sso | head -n 1 
</pre></div>


<p>I used different ORACLE_HOME&#8217;s and created with each home 2 wallets of the same login type and compared the output. Then, I identified the third number group of the first line to be constant for the same type of wallet and different for another type of wallet. E.g. for an auto_login_local wallet it is always 034116.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
0000000 174241 034116 000000 003000 000000 020400 012406 010137 #auto_login_local
0000000 174241 033116 000000 003000 000000 020400 033406 125027 #auto_login (global)
0000000 174241 033516 000000 003000 000000 020400 065406 020030 #auto_login_only
</pre></div>


<p>Hint: the output is dependent of the endianness of the system. On X86 architecture with little-endian (example above), the od output of an auto_login_local wallet is &#8220;034116&#8221;, on a big-endian system (e.g. AIX) it is &#8220;047070&#8221;. If you copy the <code>cwallet.sso</code> from an AIX system to Linux, you will get the same number group as from a Linux wallet. So the output is dependent on the platform where <code>od</code> is called, and not on the platform where the wallet was created. Below you can see the output of a big-endian system:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
0000000  120770 047070 000000 000006 000000 000041 003313 117047 #auto_login_local
0000000  120770 047066 000000 000006 000000 000041 003321 045646 #auto_login
0000000  120770 047067 000000 000006 000000 000041 003047 065254 #auto_login_only
</pre></div>


<p>To get the wallet-type, you can use the following shell-script code</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
  if &#x5B; -f cwallet.sso ]; then
    autologincode=$( od cwallet.sso |head -n 1 | awk &#039;{print $3}&#039; )
    echo autologincode=$autologincode
    case $autologincode in
      047066|033116) type=&quot;auto_login (global)&quot;; test -f ewallet.p12 || type=&quot;$type, but ewallet.p12 is missing&quot; ;;
      047067|033516) type=&quot;auto_login_only&quot;;     test -f ewallet.p12 &amp;&amp; type=&quot;$type, but unknown ewallet.p12 present&quot; ;;
      047070|034116) type=&quot;auto_login_local&quot;;    test -f ewallet.p12 || type=&quot;$type, but ewallet.p12 is missing&quot; ;;
      *) echo &quot;unknown&quot; ;;
    esac
    echo &quot;Wallet-type is $type&quot;
  elif &#x5B; -f ewallet.p12 ]; then
    echo &quot;Wallet-type is without autologin&quot;
  else
    echo &quot;No Oracle wallet in this directory&quot;
  fi
</pre></div>


<h2 class="wp-block-heading" id="h-converting-wallets">Converting wallets</h2>



<p>To convert an auto_login or auto_login_local wallet to a non-auto-login wallet: simply remove the cwallet.sso file.</p>



<p>As long as the ewallet.p12 file exists, it can be converted to an auto_login or auto_login_local wallet</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
orapki wallet create -wallet . -auto_login 
orapki wallet create -wallet . -auto_login_local
</pre></div>


<p>But you can not create an auto_login_only wallet from another wallet type (existing <code>ewallet.p12</code>). The error-message is <code>PKI-02001: A wallet already exists at: .</code></p>



<p>And to create an auto_login(_local) wallet from an auto_login_only wallet? The command above for conversion works. The type is changed to auto_login, but: Oracle forgets to create the ewallet.p12 file. As a result, you have a wallet that can no longer be modified! 🙁</p>



<p>With Oracle tools it seems not to be directly possible, you have to rebuild the wallet. Certificates can be moved by export/import, but credentials have to be re-added manually. </p>



<p>To move the certificates, first, convert the proprietary cwallet.sso file to a <a href="https://en.wikipedia.org/wiki/Java_KeyStore">jks keystore</a>.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
read PW  # type the password (it is not stored in the shell-history)
orapki wallet pkcs12_to_jks \
  -wallet . \
  -jksKeyStoreLoc ewallet.jks \
  -jksKeyStorepwd $PW
</pre></div>


<p>Then, you can convert the jks to a p12 file</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
mkdir new_wallet/
keytool -importkeystore \
    -srckeystore ewallet.jks \
    -srcstoretype JKS \
    -srcstorepass &quot;$PW&quot; \
    -destkeystore new_wallet/ewallet.p12 \
    -deststoretype PKCS12 \
    -deststorepass &quot;$PW&quot;
</pre></div>


<p>If it only contains trusted certificates, it can be converted to an Oracle auto_login wallet:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
orapki wallet create -wallet new_wallet/ -pwd $PW -auto_login  #or -auto_login_local
orapki wallet display -wallet new_wallet/   #should now work without password
</pre></div>


<p>But if it also contains &#8220;User Certificates&#8221; (server certificate  and private key), you can use the command above and it looks like an auto_login wallet. But: It ignores the auto-login part, it always asks for a password! 🙁</p>



<p>To transfer the user certificate, you have to import it in an empty Oracle wallet</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
cd new_wallet
mv ewallet.p12 container.p12
rm *wallet.*
orapki wallet create -wallet . -auto_login   #create a new, empty wallet
orapki wallet import_pkcs12 -wallet . -pwd $PW -pkcs12file container.p12 -pkcs12pwd $PW
</pre></div>


<p>Afterwards, we have a working auto_login wallet with the user certificate and some, but probably not all, trusted certificates. Import the missing trusted certificates afterwards</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
orapki wallet add -wallet . -cert Pcs3ss_v4.pem -trusted_cert  -pwd $PW
</pre></div>


<h2 class="wp-block-heading" id="h-summary">Summary</h2>



<p>The auto-login feature of Oracle wallets, which is implemented by the proprietary <code>cwallet.sso</code> file, enables non-interactive logins and startup of SSL Listeners within the Oracle world, e.g. for batch processing.</p>



<p>For security reasons, keep an eye on the filesystem permissions. If possible, restrict the access to the owner only (oracle, chmod 600). If there is no need to copy wallets to different servers, use the auto_login<strong>_local</strong> wallet type. The advantage is that if someone copies the <code>cwallet.sso</code> file to another host, it can not use the auto-login feature.</p>



<p>The auto_login_only wallet is a good solution to store trusted certificates (which are publicly available). Use-case is a wallet for client-connects with TCPS and no need for client-authentication.</p>



<p>All wallet-types, except auto_login_only, can be converted with <code>orapki</code> from each type to another. </p>



<p>Converting an auto_login_only wallet is partially possible with a combination of openssl- and Oracle tools.</p>
<p>L’article <a href="https://www.dbi-services.com/blog/different-types-of-oracle-wallets/">Different types of Oracle wallets</a> est apparu en premier sur <a href="https://www.dbi-services.com/blog">dbi Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dbi-services.com/blog/different-types-of-oracle-wallets/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Setting up Microsoft Defender &#038; Arc on Linux</title>
		<link>https://www.dbi-services.com/blog/setting-up-microsoft-defender-arc-on-linux/</link>
					<comments>https://www.dbi-services.com/blog/setting-up-microsoft-defender-arc-on-linux/#respond</comments>
		
		<dc:creator><![CDATA[Open source Team]]></dc:creator>
		<pubDate>Tue, 06 May 2025 12:39:33 +0000</pubDate>
				<category><![CDATA[Azure]]></category>
		<category><![CDATA[Operating systems]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Arc]]></category>
		<category><![CDATA[Defender]]></category>
		<category><![CDATA[Linux]]></category>
		<guid isPermaLink="false">https://www.dbi-services.com/blog/?p=38281</guid>

					<description><![CDATA[<p>Before we explore Microsoft Defender &#38; Arc, I must clarify: Setting up Microsoft Defender and Arc on a Linux server, especially one without internet access and with robust security monitoring and hardening, may seem counterintuitive. However, because the software was already purchased, managers insist on deploying the same product across all servers. So here we [&#8230;]</p>
<p>L’article <a href="https://www.dbi-services.com/blog/setting-up-microsoft-defender-arc-on-linux/">Setting up Microsoft Defender &amp; Arc on Linux</a> est apparu en premier sur <a href="https://www.dbi-services.com/blog">dbi Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Before we explore Microsoft Defender &amp; Arc, I must clarify: </p>



<p>Setting up Microsoft Defender and Arc on a Linux server, especially one without internet access and with robust security monitoring and hardening, may seem counterintuitive. However, because the software was already purchased, managers insist on deploying the same product across all servers. So here we are, deploying a Microsoft closed source antivirus on a Linux open source operating system. But don&#8217;t get me wrong, Defender and Arc do have some benefits which make it worth installing, you can find those in the Summary below.</p>



<p>The whole setup was done based on the Microsoft official best practice:<br><a href="https://learn.microsoft.com/en-us/defender-endpoint/linux-install-manually">https://learn.microsoft.com/en-us/defender-endpoint/linux-install-manually</a></p>



<p>First, for all Distributions we will need the On-boarding script generated out of your companies Microsoft Azure environment. For that we need to go into the Microsoft Defender Portal:</p>



<ul class="wp-block-list">
<li>Head to Settings &gt; Endpoints &gt; Device Management &gt; Onboarding.</li>



<li>Next, in the first drop down, pick &#8220;Linux Server&#8221; as the operating system. In the second drop down, choose &#8220;Local Script&#8221; as the deployment method.</li>
</ul>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="785" height="439" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/05/microschrott.png" alt="" class="wp-image-38290" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/05/microschrott.png 785w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/05/microschrott-300x168.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/05/microschrott-768x429.png 768w" sizes="auto, (max-width: 785px) 100vw, 785px" /></figure>



<ul class="wp-block-list">
<li>After that, click &#8220;Download onboarding package&#8221; and save the file as WindowsDefenderATPOnboardingPackage.zip</li>
</ul>



<p>Finally, unzip that file and drop it in the home directory of each server you want to join.</p>



<h2 class="wp-block-heading" id="h-preparing-microsoft-defender-arc-for-rpm-based-distributions">Preparing Microsoft Defender/ Arc for RPM-Based Distributions</h2>



<pre class="wp-block-code"><code># Jump to your home folder
$ cd

# Download the official azure installation script for defender
$ curl -o mde_install.sh https://github.com/microsoft/mdatp-xplat/blob/master/linux/installation/mde_installer.sh

# In case your Linux server has no direct internet access you can use curl with a Proxy. Use -x:
curl -x http://proxy.yourdomain.ch:80 -o mde_install.sh https://github.com/microsoft/mdatp-xplat/blob/master/linux/installation/mde_installer.sh

# Install dependencies which will be needed for the process
$ sudo yum install yum-utils

# Add the official repository for the defender and arc packages
$ sudo yum-config-manager --add-repo=https://packages.microsoft.com/config/rhel/8/prod.repo

# Trust the repositories by importing the GPG-Key
$ sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc

# Install both packages 
$ sudo apt-get install mdatp azcmagent

# Add a proxy to both the mdatp (Defender) and azcmagent (ARC)
$ sudo mdatp config proxy set --value http://proxy.yourdomain.ch:80
$ sudo azcmagent_proxy add http://proxy.yourdomain.ch:80</code></pre>



<h2 class="wp-block-heading" id="h-preparing-microsoft-defender-arc-for-sles-suse">Preparing Microsoft Defender/ Arc for SLES/ SUSE</h2>



<pre class="wp-block-code"><code># Jump to your home folder
$ cd

# Download the official azure installation script for defender
$ curl -o mde_install.sh https://github.com/microsoft/mdatp-xplat/blob/master/linux/installation/mde_installer.sh

# In case your Linux server has no direct internet access you can use curl with a Proxy. Use -x:
curl -x http://proxy.yourdomain.ch:80 -o mde_install.sh https://github.com/microsoft/mdatp-xplat/blob/master/linux/installation/mde_installer.sh

# Add the official repository for the defender and arc packages
$ sudo zypper addrepo -c -f -n microsoft-prod https://packages.microsoft.com/config/sles/15/prod.repo

# Trust the repositories by accepting the GPG key after the zypper refresh
$ sudo zypper refresh

# Install both packages 
$ sudo zypper install mdatp azcmagent

# Add a proxy to both the mdatp (Defender) and azcmagent (ARC)
$ sudo mdatp config proxy set --value http://proxy.yourdomain.ch:80
$ sudo azcmagent_proxy add http://proxy.yourdomain.ch:80</code></pre>



<h2 class="wp-block-heading" id="h-preparing-microsoft-defender-arc-for-debian">Preparing Microsoft Defender/ Arc for Debian</h2>



<pre class="wp-block-code"><code># Jump to your home folder
$ cd

# Download the official azure installation script for defender
curl -o mde_install.sh https://github.com/microsoft/mdatp-xplat/blob/master/linux/installation/mde_installer.sh

# In case your Linux server has no direct internet access you can use curl with a Proxy. Use -x:
$ curl -x http://proxy.yourdomain.ch:80 -o mde_install.sh https://github.com/microsoft/mdatp-xplat/blob/master/linux/installation/mde_installer.sh

# Install dependencies which will be needed for the process
$ sudo apt-get install curl libplist-utils gpg gnupg apt-transport-https

# Add the new Repositories to your server
$ curl -o microsoft.list https://packages.microsoft.com/config/debian/12/prod.list

# Move the new repo-file to the apt repository folder
$ sudo mv microsoft.list /etc/apt/sources.list.d/microsoft-prod.list

# Download and import the GPG key for the new repositories via proxy:
$ curl -x http://proxy.yourdomain.ch:80 -sSL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo tee /usr/share/keyrings/microsoft-prod.gpg &gt; /dev/null

# Refresh all repositories
$ sudo apt update

# Install both packages 
$ sudo apt-get install mdatp azcmagent

# Add a proxy to both the mdatp (Defender) and azcmagent (ARC)
$ sudo mdatp config proxy set --value http://proxy.yourdomain.ch:80
$ sudo azcmagent_proxy add http://proxy.yourdomain.ch:80</code></pre>



<h2 class="wp-block-heading" id="h-preparing-microsoft-defender-arc-for-ubuntu">Preparing Microsoft Defender/ Arc for Ubuntu</h2>



<pre class="wp-block-code"><code># Jump to your home folder
$ cd

# Download the official azure installation script for defender
curl -o mde_install.sh https://github.com/microsoft/mdatp-xplat/blob/master/linux/installation/mde_installer.sh

# In case your Linux server has no direct internet access you can use curl with a Proxy. Use -x:
$ curl -x http://proxy.yourdomain.ch:80 -o mde_install.sh https://github.com/microsoft/mdatp-xplat/blob/master/linux/installation/mde_installer.sh

# Install dependencies which will be needed for the process
$ sudo apt-get install curl libplist-utils gpg gnupg apt-transport-https

# Add the new GPG-Key to your server and install it
$ curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor &gt; microsoft.gpg

$ sudo install -o root -g root -m 644 microsoft.gpg /usr/share/keyrings/
rm microsoft.gpg

# Create a new Repository file and update your apt package manager
$ sudo sh -c 'echo "deb &#091;arch=amd64 signed-by=/usr/share/keyrings/microsoft.gpg] https://packages.microsoft.com/ubuntu/$(lsb_release -rs)/prod $(lsb_release -cs) main" &gt;&gt; /etc/apt/sources.list.d/microsoft-ubuntu-$(lsb_release -cs)-prod.list'

# Refresh all repositories
$ sudo apt update

# Install both packages 
$ sudo apt-get install mdatp azcmagent

# Add a proxy to both the mdatp (Defender) and azcmagent (ARC)
$ sudo mdatp config proxy set --value http://proxy.yourdomain.ch:80
$ sudo azcmagent_proxy add http://proxy.yourdomain.ch:80</code></pre>



<h2 class="wp-block-heading" id="h-setup-configure-defender-arc-on-all-distributions">Setup/ Configure Defender/ Arc on all Distributions</h2>



<pre class="wp-block-code"><code># Make sure the Azure script has access to be executed
$ sudo chmod +x mde_installer.sh

# Execute the Azure script with your generated Onboarding script
$ sudo ./mde_installer.sh -o WindowsDefenderATPOnboardingPackage.py
# This step shall return a state “Onboarded”

# We can now additionally activate the real time protection
$ sudo mdatp config real-time-protection --value enabled

# One can check the health of the setup with running
$ sudo mdatp health

# Now we can add the Linux server to the ARC
$ sudo azcmagent connect -l switzerlandnorth -s &lt;SubscriptionID&gt; -g &lt;GroupPolicy&gt;
# This step will return a webpage on your Azure including a unique key which we need to type in into the login prompt. This can only be done if your account ahs sufficient rights to maintain and add new clients to your organizations Azure</code></pre>



<h2 class="wp-block-heading" id="h-summary-amp-hints">Summary &amp; Hints</h2>



<p>This technical guide will help you connect any Linux server to your existing Azure Defender and Arc portal. Once set up, you’ll unlock some great benefits for securing your systems. Here’s what you get:</p>



<ul class="wp-block-list">
<li>Real-time threat protection: Defender instantly scans files for malware, viruses, or other threats as they pop up on your Linux servers.</li>



<li>Cross-platform support: It works seamlessly with Windows, macOS, and more, so you can manage all devices from one place.</li>



<li>Advanced threat detection: In addition, it uses smart cloud analytics to spot serious threats like ransomware or sneaky zero-day attacks.</li>



<li>Vulnerability checks: Finds weak spots in your Linux setup, like outdated apps or bad configs, and suggests fixes.</li>



<li>Centralized management: Furthermore, you can control all your Linux servers from the Defender portal, making updates and monitoring a breeze.</li>



<li>Easier compliance: Helps meet strict security standards (like Cyber Essentials) with built-in tools for Linux environments.</li>
</ul>



<p>It may take a bit for your newly added Linux machines to appear in the Defender and Arc Azure Portal. Depending on your data center’s location, it could take up to half a day for the portal to fully sync and display all your Linux systems’ details.</p>



<p></p>
<p>L’article <a href="https://www.dbi-services.com/blog/setting-up-microsoft-defender-arc-on-linux/">Setting up Microsoft Defender &amp; Arc on Linux</a> est apparu en premier sur <a href="https://www.dbi-services.com/blog">dbi Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dbi-services.com/blog/setting-up-microsoft-defender-arc-on-linux/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>dbo vs. db_owner in SQL Server – What are the differences between them?</title>
		<link>https://www.dbi-services.com/blog/dbo-vs-db_owner-in-sql-server-what-are-the-differences-between-them/</link>
					<comments>https://www.dbi-services.com/blog/dbo-vs-db_owner-in-sql-server-what-are-the-differences-between-them/#respond</comments>
		
		<dc:creator><![CDATA[Roger Schönmann]]></dc:creator>
		<pubDate>Mon, 20 Jan 2025 10:16:00 +0000</pubDate>
				<category><![CDATA[Database management]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[db_owner]]></category>
		<category><![CDATA[dbo]]></category>
		<category><![CDATA[owner]]></category>
		<category><![CDATA[SQL Security]]></category>
		<guid isPermaLink="false">https://www.dbi-services.com/blog/?p=36538</guid>

					<description><![CDATA[<p>During the last years working with customers and teaching them in security topics, I realised that a lot of DBAs are not familiar with or aware of the differences between the two “owner” existing in SQL Server. That&#8217;s why I decided to write a blog about it. Well, in SQL Server we are dealing with [&#8230;]</p>
<p>L’article <a href="https://www.dbi-services.com/blog/dbo-vs-db_owner-in-sql-server-what-are-the-differences-between-them/">dbo vs. db_owner in SQL Server – What are the differences between them?</a> est apparu en premier sur <a href="https://www.dbi-services.com/blog">dbi Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>During the last years working with customers and teaching them in security topics, I realised that a lot of DBAs are not familiar with or aware of the differences between the two “owner” existing in SQL Server.  That&#8217;s why I decided to write a blog about it.</p>



<p>Well, in SQL Server we are dealing with two principals in terms of “owning” a database:</p>



<ul class="wp-block-list">
<li>dbo</li>



<li>db_owner</li>
</ul>



<p>Principals in terms of SQL Server are entries that can request SQL Server resources. <br>We have so called server principals which are operating on instance-level &#8211; here we are talking about logins. At the other hand we have database principals which are operating at database-level &#8211; here we are talking about users.<br>While &#8220;<strong>dbo</strong>&#8221; is a single principal (a database-level user) who owns effectively the database, &#8220;<strong>db_owner</strong>&#8221; is a database role which can contain multiple users (the role itself is a principal as well as all their members) equipped with the rights to do any operation within the database – means executing DML (Data Manipulation Language – statements like SELECT, INSERT, UPDATE and DELETE) as well as DDL (Data Definition Language – statements like ALTER DATABASE etc.) and DCL (Data Control Language – statements like GRANT and REVOKE) against the database engine.<br>Furthermore every principal which is member of the server role &#8220;sysadmin&#8221; is not working under his own user in a database, he is mapped implicitly as &#8220;<strong>dbo</strong>&#8221; into each database.<br>There are tiny little differences between the two principals &#8220;<strong>dbo</strong>&#8221; and &#8220;<strong>db_owner</strong>&#8221; that I want to show you in several demos.</p>



<p>By the way: for my demo I’m using the new SSMS 21 which is available in preview these days. My colleague Stéphane Haby already written a <a href="https://www.dbi-services.com/blog/new-sql-server-management-studio-version-21-first-test/">blog post about the installation of the newest release of SSMS 21.</a></p>



<p>The range of functions and authorizations of the user &#8220;<strong>dbo</strong>&#8221; and members of the database role &#8220;<strong>db_owner</strong>&#8221; are quiet the same, but they differ in the following points:</p>



<ol class="wp-block-list">
<li>The &#8220;<strong>dbo</strong>&#8221; is able to restore his own database (WITH REPLACE) while members of the role &#8220;<strong>db_owner</strong>&#8221; are not</li>



<li>All security checks are skippt when you acting as &#8220;<strong>dbo</strong>&#8220;, means DENYs are ignored meanwhile DENYs are taken into account when operating as a member of the role &#8220;<strong>db_owner</strong>&#8220;</li>
</ol>



<p>Let’s dig into the demo: After creating the database &#8220;dbo_vs_dbowner&#8221; I&#8217;ve created two logins with descriptive names:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="367" height="152" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image.png" alt="" class="wp-image-36539" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image.png 367w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-300x124.png 300w" sizes="auto, (max-width: 367px) 100vw, 367px" /></figure>



<p>The login “<strong>Ced_dbo</strong>” is the owner of the database, the login “<strong>Ced_dbowner</strong>” is member of the database role db_owner:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="658" height="247" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-1.png" alt="" class="wp-image-36540" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-1.png 658w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-1-300x113.png 300w" sizes="auto, (max-width: 658px) 100vw, 658px" /></figure>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="710" height="403" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-2.png" alt="" class="wp-image-36541" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-2.png 710w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-2-300x170.png 300w" sizes="auto, (max-width: 710px) 100vw, 710px" /></figure>



<p>The setup for the demo is now complete.<br>Now we come to the section, where I want to show you the different behaviour when working with each of them.</p>



<h2 class="wp-block-heading" id="h-backup-restore"><strong>BACKUP/RESTORE</strong></h2>



<p>Let’s check if we have enough permissions to backup the database first.<br><strong>Ced_dbo</strong> – of course, there is no problem to perform a backup of his own database:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="961" height="283" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-19.png" alt="" class="wp-image-36573" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-19.png 961w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-19-300x88.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-19-768x226.png 768w" sizes="auto, (max-width: 961px) 100vw, 961px" /></figure>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="961" height="160" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-4.png" alt="" class="wp-image-36543" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-4.png 961w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-4-300x50.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-4-768x128.png 768w" sizes="auto, (max-width: 961px) 100vw, 961px" /></figure>



<p><strong>Ced_dbowner</strong> &#8211; no problem to perform a backup of the database as well:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="961" height="293" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-6.png" alt="" class="wp-image-36545" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-6.png 961w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-6-300x91.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-6-768x234.png 768w" sizes="auto, (max-width: 961px) 100vw, 961px" /></figure>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="961" height="157" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-7.png" alt="" class="wp-image-36546" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-7.png 961w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-7-300x49.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-7-768x125.png 768w" sizes="auto, (max-width: 961px) 100vw, 961px" /></figure>



<p>Now, let’s take a look at the behaviour when performing a restore.<br><strong>Ced_dbo</strong> – Restore is working properly here:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="961" height="316" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-8.png" alt="" class="wp-image-36547" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-8.png 961w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-8-300x99.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-8-768x253.png 768w" sizes="auto, (max-width: 961px) 100vw, 961px" /></figure>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="816" height="159" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-9.png" alt="" class="wp-image-36548" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-9.png 816w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-9-300x58.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-9-768x150.png 768w" sizes="auto, (max-width: 816px) 100vw, 816px" /></figure>



<p><strong>Ced_dbowner</strong> – Performing a restore of the database is not possible under this credentials, because he is neither the owner nor member of the server role “db_creator” or “sysadmin”:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="961" height="306" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-10.png" alt="" class="wp-image-36549" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-10.png 961w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-10-300x96.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-10-768x245.png 768w" sizes="auto, (max-width: 961px) 100vw, 961px" /></figure>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="671" height="174" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-11.png" alt="" class="wp-image-36550" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-11.png 671w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-11-300x78.png 300w" sizes="auto, (max-width: 671px) 100vw, 671px" /></figure>



<p><strong><span style="color: red">Caution: Performing a restore of his own database is only possible for the user Ced_dbo if he’s providing the parameter WITH REPLACE within the restore statement. If he drops his database first – yes this operation is allowed to execute for the &#8220;dbo&#8221; as well as for members of the database role “db_owner” – and tries to restore it afterwards, the operation will fail!</span></strong><br>This makes sense because the master database keeps track of the owner of all databases. If a database is dropped, this information will be lost and SQL Server no longer has a clue who the owner of the database is/was and we need server level permissions (e.g. dbcreator or sysadmin) to create the database again from the backup.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="961" height="357" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-12.png" alt="" class="wp-image-36551" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-12.png 961w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-12-300x111.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-12-768x285.png 768w" sizes="auto, (max-width: 961px) 100vw, 961px" /></figure>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="622" height="186" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-13.png" alt="" class="wp-image-36552" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-13.png 622w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-13-300x90.png 300w" sizes="auto, (max-width: 622px) 100vw, 622px" /></figure>



<p><a href="https://learn.microsoft.com/en-us/sql/relational-databases/backup-restore/restore-database-general-page?view=sql-server-ver16#permissions">https://learn.microsoft.com/en-us/sql/relational-databases/backup-restore/restore-database-general-page?view=sql-server-ver16#permissions</a></p>



<p></p>



<h2 class="wp-block-heading" id="h-bypassing-security-checks"><strong>Bypassing Security Checks</strong></h2>



<p>Now we are goinig to check out the different behaviour of the sessions with our 2 users mentioned above under this point.<br>Due to the fact that Microsoft also uses the principle of inheritance of authorisations in the SQL Server environment, DENY had to be added to the well-known GRANT and REVOKE control commands of a DBMS. This differs from other DBMS like for example Oracle. Generally speaking, within SQL Server we are confronted with the fact that a DENY is overriding every other permission set for a user or group.</p>



<p>SQL Server knows the concept of bypassing security checks when we are connected with users who are members of the server role “sysadmin” and owner of databases as well – means for all types of users like this, DENYs are completely ignored.</p>



<p>A few weeks ago I prepared myself to teach our SQL Server <a href="https://www.dbi-services.com/courses/microsoft-sql-server-dba-essential-training/">dbi-services course “DBA ESSENTIALS”</a> and I was astonished to realise that things has changed obviously when working with SQL Server 2022. Security bypassing seemed to be skippt by Microsoft, because the database owner was unable to do stuff which was denied for public as well as all the other users, but…</p>



<p>…after performing countless tests on different versions of SQL Server 2022, with older versions of SSMS and so on and so forth I&#8217;m able to to confirm, that SQL Server 2022 behaves the same way as always and as expected. I haven’t got a clue what magic happens within my testing environment during my preparation <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f60a.png" alt="😊" class="wp-smiley" style="height: 1em; max-height: 1em;" /><br>Let’s dig into the next demo to illustrate and prove that things are behaving the same way the always did.<br>First of all, I created the Stored Procedure called “spr_getInfo” within the database as follows:</p>



<pre class="wp-block-code"><code>USE &#091;dbo_vs_dbowner]
GO
CREATE PROCEDURE spr_getInfo
AS
BEGIN
  SELECT * FROM &#091;dbo_vs_dbowner].&#091;dbo].&#091;T1]
  WHERE T1_ID = 3
END
</code></pre>



<p>Then I set a DENY to execute this Stored Procedure for all users:</p>



<pre class="wp-block-code"><code>USE &#091;dbo_vs_dbowner]
GO
DENY EXECUTE ON OBJECT::dbo.spr_getInfo TO &#091;public]
GO</code></pre>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="754" height="719" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-14.png" alt="" class="wp-image-36553" style="width:606px;height:auto" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-14.png 754w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-14-300x286.png 300w" sizes="auto, (max-width: 754px) 100vw, 754px" /></figure>



<p><strong>Ced_dbowner</strong> – even this user is member of the database role “db_owner” which is granted to do everything within the database he is not allowed to execute the Stored Procedure because the DENY overrides the GRANT in terms of executing this Stored Procedure as mentioned above:</p>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="725" height="419" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-15.png" alt="" class="wp-image-36554" style="width:500px;height:auto" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-15.png 725w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-15-300x173.png 300w" sizes="auto, (max-width: 725px) 100vw, 725px" /></figure>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="961" height="126" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-16.png" alt="" class="wp-image-36555" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-16.png 961w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-16-300x39.png 300w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-16-768x101.png 768w" sizes="auto, (max-width: 961px) 100vw, 961px" /></figure>



<p>Selecting from the table directly is nevertheless allowed (same statement as used within the Stored Procedure), because the DENY impacts only the execution of the Stored Procedure but not the SELECT on the base table:</p>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="724" height="542" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-17.png" alt="" class="wp-image-36556" style="width:501px;height:auto" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-17.png 724w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-17-300x225.png 300w" sizes="auto, (max-width: 724px) 100vw, 724px" /></figure>



<p>Now, let’s have a look how the execution behaves under the owner of the database.<br><strong>Ced_dbo</strong> – as mentioned at the beginning of this section, for the owner of the database the DENY is ignored and a query result is being returned when the Stored Procedure is executed:</p>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="724" height="516" src="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-18.png" alt="" class="wp-image-36557" style="width:507px;height:auto" srcset="https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-18.png 724w, https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2025/01/image-18-300x214.png 300w" sizes="auto, (max-width: 724px) 100vw, 724px" /></figure>



<h2 class="wp-block-heading" id="h-conclusion"><strong>Conclusion</strong></h2>



<p>From my point of view, as a DBA it’s very important to know the tiny differences between &#8220;<strong>dbo</strong>&#8221; and members of the database role “<strong>db_owner</strong>” to avoid unpleasant surprises in our daily business.<br>And last but not least: things behave in the same manner as we are familiar with since a long time ago. Whether this is an advantage or a disadvantage remains a philosophical question…</p>
<p>L’article <a href="https://www.dbi-services.com/blog/dbo-vs-db_owner-in-sql-server-what-are-the-differences-between-them/">dbo vs. db_owner in SQL Server – What are the differences between them?</a> est apparu en premier sur <a href="https://www.dbi-services.com/blog">dbi Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dbi-services.com/blog/dbo-vs-db_owner-in-sql-server-what-are-the-differences-between-them/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Page Caching using Disk: Enhanced 
Lazy Loading (feed)

Served from: www.dbi-services.com @ 2026-05-25 22:12:28 by W3 Total Cache
-->