<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Keshav Malik]]></title><description><![CDATA[Full Stack Software Developer & Security Engineer ⚡]]></description><link>https://blog.theinfosecguy.xyz</link><generator>RSS for Node</generator><lastBuildDate>Thu, 16 Apr 2026 08:13:34 GMT</lastBuildDate><atom:link href="https://blog.theinfosecguy.xyz/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Building a CRUD API with FastAPI and Supabase: A Step-by-Step Guide]]></title><description><![CDATA[Are you looking for a way to quickly and easily create a CRUD API? If so, then using FastAPI along with Supabase is the perfect solution. With this step-by-step guide, you’ll learn how easy it is to build an API that can handle all of your data needs...]]></description><link>https://blog.theinfosecguy.xyz/building-a-crud-api-with-fastapi-and-supabase-a-step-by-step-guide</link><guid isPermaLink="true">https://blog.theinfosecguy.xyz/building-a-crud-api-with-fastapi-and-supabase-a-step-by-step-guide</guid><category><![CDATA[Python]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Developer]]></category><category><![CDATA[FastAPI]]></category><category><![CDATA[software development]]></category><dc:creator><![CDATA[Keshav Malik]]></dc:creator><pubDate>Sat, 18 Feb 2023 13:31:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1676724889911/a0fecf39-38ca-43ef-8f6a-b88e5a21a572.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Are you looking for a way to quickly and easily create a CRUD API? If so, then using FastAPI along with Supabase is the perfect solution. With this step-by-step guide, you’ll learn how easy it is to build an API that can handle all of your data needs.</p>
<p>You’ll be able to add and query data from your database, and even update or delete records. All of this can be done in just a few simple steps! So if you’re ready to get started creating your own powerful CRUD API with FastAPI and Supabase, read on!</p>
<h2 id="heading-what-is-supabase">What is Supabase?</h2>
<p><a target="_blank" href="https://supabase.com/">Supabase</a> is an open-source Firebase alternative. It provides the same functionality and architecture as Firebase, but with a focus on Postgres databases instead of NoSQL storage.</p>
<p>Supabase provides a number of features including real-time streaming, authentication, storage, and more. It's designed to be easy to use for developers who are familiar with SQL databases such as Postgres or MySQL. With Supabase, you can quickly and easily set up a CRUD API (and much more) that can handle all your data needs.</p>
<h2 id="heading-what-is-fastapi">What is FastAPI?</h2>
<p><a target="_blank" href="https://fastapi.tiangolo.com/">FastAPI</a> is an open-source web framework built on top of Python's highly popular asynchronous web framework, Starlette. It is designed to help developers create high-performance, reliable, and secure APIs quickly and easily.</p>
<p>FastAPI makes use of industry-standard tools such as <a target="_blank" href="https://www.openapis.org/">OpenAPI</a> and JSON Schema, ensuring that all APIs created using it are fully compatible with existing APIs used by other applications. Its architecture is also specifically designed for scalability so that developers can easily scale their projects as their user base grows.</p>
<h2 id="heading-setting-up-supabase-project">Setting up Supabase Project</h2>
<p>To integrate Supabase with Python, we need Supabase URL &amp; API Key. We can get these directly from Supabse. First, create a project in Supabase from the Supabase dashboard.</p>
<p>Once the project is up, navigate to <strong>Project Setting &lt; API</strong> and copy the URL &amp; API Key.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676714180558/4c9d3773-61aa-4e35-8967-5a178195675a.png" alt class="image--center mx-auto" /></p>
<p>After copying the URL &amp; Key, navigate to the Tables tab and create <code>users</code> table and add 3 columns: <code>name</code> , <code>email</code> , and <code>password</code> .</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676715599046/dad63bd4-9884-446e-bbb1-90a0fe7930e6.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-integrating-fastapi-with-supabase">Integrating FastAPI with Supabase</h2>
<p>Before we integrate FastAPI with Supabase, let's first create a virtual environment and install the required dependencies.</p>
<pre><code class="lang-bash">mkdir fastapi-supabase; <span class="hljs-built_in">cd</span> fastapi-supabase
pipenv shell
pip install <span class="hljs-string">"fastapi[all]"</span> bcrypt supabase
</code></pre>
<p><strong>🚨Note:</strong> <em>If you don't have</em> <code>pipenv</code> <em>installed, you can install it using the</em> <code>sudo apt install pipenv</code> <em>command.</em></p>
<p>Once all dependencies are installed, create a <code>config.py</code> file to store secrets. Although storing secrets in plain text is never recommended, for the sake of ease of this tutorial, let's add the secrets in the config file.</p>
<pre><code class="lang-bash">url=<span class="hljs-string">"https://abc.supabase.co"</span>
api=<span class="hljs-string">"dummy-api"</span>
</code></pre>
<p><strong>💡Learn more</strong>: <a target="_blank" href="https://blog.gitguardian.com/how-to-handle-secrets-in-python/">How to Handle Secrets in Python</a></p>
<p>Now, let's create a FastAPI application. First, create an <code>app</code> directory containing the <code>main.py</code> file and paste the following code.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI

app = FastAPI()

app.get(<span class="hljs-string">"/"</span>)(<span class="hljs-keyword">lambda</span>: {<span class="hljs-string">"Hello"</span>: <span class="hljs-string">"World"</span>})
</code></pre>
<p>This is a bare-minimum FastAPI application running on <a target="_blank" href="http://127.0.0.1:8000/">http://127.0.0.1:8000/</a> and returning <code>{"Hello": "World"}</code> on <code>/</code> route. Start the server using the command:</p>
<pre><code class="lang-bash">uvicorn app.main:app --reload
</code></pre>
<h2 id="heading-fastapi-supabase-connection">FastAPI Supabase Connection</h2>
<p>We have successfully created the Supabase project and FastAPI application. Now let's connect to Supabase. Create a <code>db</code> directory and add a <code>supabase.py</code> file with the following code. Also, add <code>__init__.py</code> file in the <code>db</code> directory.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> supabase <span class="hljs-keyword">import</span> Client, create_client
<span class="hljs-keyword">from</span> config <span class="hljs-keyword">import</span> api, url

api_url: str = url
key: str = api

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_supabase_client</span>():</span>
    supabase: Client = create_client(url, key)
    <span class="hljs-keyword">return</span> supabase
</code></pre>
<p>We can now import <code>create_supabase_client</code> function in our <code>main.py</code> file to connect to Supabase.</p>
<h2 id="heading-crud-api-using-supabase-andamp-fastapi">CRUD API using Supabase &amp; FastAPI</h2>
<p>We have successfully connected to Supabase. Now, let's create a route to add data in the table but before we do that, let's first create a <a target="_blank" href="https://docs.pydantic.dev/usage/models/">Pydantic BaseModel</a> which we will use to validate the request body. Create a <code>models.py</code> file in the <code>app</code> directory and add the following code.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> pydantic <span class="hljs-keyword">import</span> BaseModel

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span>(<span class="hljs-params">BaseModel</span>):</span>
    name: str
    email: str
    password: str
</code></pre>
<p>Now, let's add the first route in the <code>main.py</code> file to add data to the <code>users</code> table.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> bcrypt
<span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI
<span class="hljs-keyword">from</span> app.models <span class="hljs-keyword">import</span> User
<span class="hljs-keyword">from</span> db.supabase <span class="hljs-keyword">import</span> create_supabase_client

app = FastAPI()

<span class="hljs-comment"># Initialize supabase client</span>
supabase = create_supabase_client()

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">user_exists</span>(<span class="hljs-params">key: str = <span class="hljs-string">"email"</span>, value: str = None</span>):</span>
    user = supabase.from_(<span class="hljs-string">"users"</span>).select(<span class="hljs-string">"*"</span>).eq(key, value).execute()
    <span class="hljs-keyword">return</span> len(user.data) &gt; <span class="hljs-number">0</span>

<span class="hljs-comment"># Create a new user</span>
<span class="hljs-meta">@app.post("/user")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_user</span>(<span class="hljs-params">user: User</span>):</span>
    <span class="hljs-keyword">try</span>:
        <span class="hljs-comment"># Convert email to lowercase</span>
        user_email = user.email.lower()
        <span class="hljs-comment"># Hash password</span>
        hased_password = bcrypt.hashpw(user.password, bcrypt.gensalt())

        <span class="hljs-comment"># Check if user already exists</span>
        <span class="hljs-keyword">if</span> user_exists(value=user_email):
            <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"User already exists"</span>}

        <span class="hljs-comment"># Add user to users table</span>
        user = supabase.from_(<span class="hljs-string">"users"</span>)\
            .insert({<span class="hljs-string">"name"</span>: user.name, <span class="hljs-string">"email"</span>: user_email, <span class="hljs-string">"password"</span>: hased_password})\
            .execute()

        <span class="hljs-comment"># Check if user was added</span>
        <span class="hljs-keyword">if</span> user:
            <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"User created successfully"</span>}
        <span class="hljs-keyword">else</span>:
            <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"User creation failed"</span>}
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        print(<span class="hljs-string">"Error: "</span>, e)
        <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"User creation failed"</span>}
</code></pre>
<p>In the above code, we have <code>/user</code> POST route to add data to the table by using <code>insert</code> function from <code>supabase</code> . We are also using <code>user_exists</code> function to check if the user exists in the table or not. Additionally, we are using <code>hashpw</code> function to hash the password before storing the password in DB (NEVER store plain text passwords in DB).</p>
<p>Now, let's test it out using <code>curl</code> . You can also use the Swagger UI or any other API testing tools (such as Postman).</p>
<pre><code class="lang-bash">curl -X POST -H <span class="hljs-string">"Content-Type: application/json"</span> -d <span class="hljs-string">'{"name": "John Doe", "email": "john.doe@example.com", "password": "password123"}'</span> http://127.0.0.1:8000/user
</code></pre>
<p><strong>🚨Note:</strong> <em>Swagger UI can be accessed by visiting the</em> <code>/docs</code> <em>or</em> <code>/redoc</code> <em>environment.</em></p>
<p>If you have followed all steps properly, you will receive the following response.</p>
<pre><code class="lang-bash">{<span class="hljs-string">"message"</span>:<span class="hljs-string">"User created successfully"</span>}
</code></pre>
<p>Let's now quickly update the <code>main.py</code> file to add functions to perform READ, UPDATE, and DELETE operations.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Union

<span class="hljs-keyword">import</span> bcrypt
<span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI
<span class="hljs-keyword">from</span> app.models <span class="hljs-keyword">import</span> User
<span class="hljs-keyword">from</span> db.supabase <span class="hljs-keyword">import</span> create_supabase_client

app = FastAPI()

<span class="hljs-comment"># Initialize supabase client</span>
supabase = create_supabase_client()

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">user_exists</span>(<span class="hljs-params">key: str = <span class="hljs-string">"email"</span>, value: str = None</span>):</span>
    user = supabase.from_(<span class="hljs-string">"users"</span>).select(<span class="hljs-string">"*"</span>).eq(key, value).execute()
    <span class="hljs-keyword">return</span> len(user.data) &gt; <span class="hljs-number">0</span>

<span class="hljs-comment"># Create a new user</span>
<span class="hljs-meta">@app.post("/user")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_user</span>(<span class="hljs-params">user: User</span>):</span>
    <span class="hljs-keyword">try</span>:
        <span class="hljs-comment"># Convert email to lowercase</span>
        user_email = user.email.lower()
        <span class="hljs-comment"># Hash password</span>
        hased_password = bcrypt.hashpw(user.password, bcrypt.gensalt())

        <span class="hljs-comment"># Check if user already exists</span>
        <span class="hljs-keyword">if</span> user_exists(value=user_email):
            <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"User already exists"</span>}

        <span class="hljs-comment"># Add user to users table</span>
        user = supabase.from_(<span class="hljs-string">"users"</span>)\
            .insert({<span class="hljs-string">"name"</span>: user.name, <span class="hljs-string">"email"</span>: user_email, <span class="hljs-string">"password"</span>: hased_password})\
            .execute()

        <span class="hljs-comment"># Check if user was added</span>
        <span class="hljs-keyword">if</span> user:
            <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"User created successfully"</span>}
        <span class="hljs-keyword">else</span>:
            <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"User creation failed"</span>}
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        print(<span class="hljs-string">"Error: "</span>, e)
        <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"User creation failed"</span>}


<span class="hljs-comment"># Retrieve a user</span>
<span class="hljs-meta">@app.get("/user")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_user</span>(<span class="hljs-params">user_id: Union[str, None] = None</span>):</span>
    <span class="hljs-keyword">try</span>:
        <span class="hljs-keyword">if</span> user_id:
            user = supabase.from_(<span class="hljs-string">"users"</span>)\
                .select(<span class="hljs-string">"id"</span>, <span class="hljs-string">"name"</span>, <span class="hljs-string">"email"</span>)\
                .eq(<span class="hljs-string">"id"</span>, user_id)\
                .execute()

            <span class="hljs-keyword">if</span> user:
                <span class="hljs-keyword">return</span> user
        <span class="hljs-keyword">else</span>:
            users = supabase.from_(<span class="hljs-string">"users"</span>)\
                .select(<span class="hljs-string">"id"</span>, <span class="hljs-string">"email"</span>, <span class="hljs-string">"name"</span>)\
                .execute()
            <span class="hljs-keyword">if</span> users:
                <span class="hljs-keyword">return</span> users
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        print(<span class="hljs-string">f"Error: <span class="hljs-subst">{e}</span>"</span>)
        <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"User not found"</span>}


<span class="hljs-comment"># Update a user</span>
<span class="hljs-meta">@app.put("/user")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">update_user</span>(<span class="hljs-params">user_id: str, email: str, name: str</span>):</span>
    <span class="hljs-keyword">try</span>:
        user_email = email.lower()

        <span class="hljs-comment"># Check if user exists</span>
        <span class="hljs-keyword">if</span> user_exists(<span class="hljs-string">"id"</span>, user_id):
            <span class="hljs-comment"># Check if email already exists</span>
            email_exists = supabase.from_(<span class="hljs-string">"users"</span>)\
                .select(<span class="hljs-string">"*"</span>).eq(<span class="hljs-string">"email"</span>, user_email)\
                .execute()
            <span class="hljs-keyword">if</span> len(email_exists.data) &gt; <span class="hljs-number">0</span>:
                <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"Email already exists"</span>}

            <span class="hljs-comment"># Update user</span>
            user = supabase.from_(<span class="hljs-string">"users"</span>)\
                .update({<span class="hljs-string">"name"</span>: name, <span class="hljs-string">"email"</span>: user_email})\
                .eq(<span class="hljs-string">"id"</span>, user_id).execute()
            <span class="hljs-keyword">if</span> user:
                <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"User updated successfully"</span>}
        <span class="hljs-keyword">else</span>:
            <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"User update failed"</span>}
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        print(<span class="hljs-string">f"Error: <span class="hljs-subst">{e}</span>"</span>)
        <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"User update failed"</span>}

<span class="hljs-comment"># Delete a user</span>
<span class="hljs-meta">@app.delete("/user")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">delete_user</span>(<span class="hljs-params">user_id: str</span>):</span>
    <span class="hljs-keyword">try</span>:        
        <span class="hljs-comment"># Check if user exists</span>
        <span class="hljs-keyword">if</span> user_exists(<span class="hljs-string">"id"</span>, user_id):
            <span class="hljs-comment"># Delete user</span>
            supabase.from_(<span class="hljs-string">"users"</span>)\
                .delete().eq(<span class="hljs-string">"id"</span>, user_id)\
                .execute()
            <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"User deleted successfully"</span>}

        <span class="hljs-keyword">else</span>:
            <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"User deletion failed"</span>}
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        print(<span class="hljs-string">f"Error: <span class="hljs-subst">{e}</span>"</span>)
        <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"User deletion failed"</span>}
</code></pre>
<p>We have added functions to perform CRUD operations on <code>users</code> table. We have used <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET"><code>GET</code></a> to get user (or list of users) information, <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST"><code>POST</code></a> to add information to the table, <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT"><code>PUT</code></a> to update <code>name</code> and <code>email</code> and <code>DELETE</code> to delete data from the table.</p>
<p>In the <code>update_user</code> function, we are receiving <code>user_id</code> , <code>name</code> and <code>email</code> from the client and checking if the user (with user_id) exists in DB or not. If yes, we update the <code>name</code> and <code>email</code> in the table.</p>
<pre><code class="lang-bash">curl -X PUT <span class="hljs-string">"http://127.0.0.1:8000/user?user_id=5&amp;email=test@gmail.com&amp;name=hello"</span>
</code></pre>
<p>In the <code>get_user</code> function, we receive <code>user_id</code> as a <a target="_blank" href="https://fastapi.tiangolo.com/tutorial/query-params/">query parameter</a>. In this case, <code>user_id</code> is optional. If <code>user_id</code> is present, we respond back with user details (without password) otherwise we send back a list of users from the <code>users</code> table.</p>
<pre><code class="lang-bash">curl http://127.0.0.1:8000/user
</code></pre>
<p>The <code>delete_user</code> simply checks if the user with <code>user_id</code> from query parameter is present in the table or not. If it's present, it deletes the user.</p>
<pre><code class="lang-bash">curl -X DELETE <span class="hljs-string">"http://127.0.0.1:8000/user?user_id=5"</span>
</code></pre>
<p><strong>🚨Note:</strong> This is just a basic tutorial for an explanation. Please thoroughly test your application before moving your application to production! 🚀</p>
<h4 id="heading-link-to-code">Link <strong>to Code</strong></h4>
<p>Here's the GitHub repository with the complete code.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/theinfosecguy/python-supabase-crud-api">https://github.com/theinfosecguy/python-supabase-crud-api</a></div>
<p> </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this blog, we discussed how developers can use FastAPI and Supabase to quickly build a powerful CRUD API. With the step-by-step guide provided, developers will be able to leverage the power of both platforms to query data from their database and even update or delete records with ease.</p>
<p>Furthermore, all APIs created using FastAPI are fully compatible with existing APIs used by other applications due to their use of industry-standard tools like OpenAPI and JSON Schema. So if you're looking for an efficient way to create your own RESTful API then give FastAPI &amp; Supabase a try today!</p>
<p>If you have any questions, feel free to send me an <a target="_blank" href="http://mailto:hello@theinfosecguy.xyz">email</a> 📧.</p>
<p>Thank you for reading! 🎉👨‍💻</p>
<p><img src="https://media0.giphy.com/media/l2R0eYcNq9rJUsVAA/giphy.gif?cid=ecf05e47vf0r1cxzkkgrpm959qpaokfa4geye5io8t1jp6u6&amp;rid=giphy.gif&amp;ct=g" alt="James Corden Hello GIF by The Late Late Show with James Corden" /></p>
]]></content:encoded></item><item><title><![CDATA[9 Things to Consider When Choosing an SCA Tool]]></title><description><![CDATA[In the past, the development of software was something that required a lot of effort and resources. Basically, every piece of code was developed in-house, and code reuse was quite limited. The situation is now the opposite. Open-source packages are s...]]></description><link>https://blog.theinfosecguy.xyz/9-things-to-consider-when-choosing-an-sca-tool</link><guid isPermaLink="true">https://blog.theinfosecguy.xyz/9-things-to-consider-when-choosing-an-sca-tool</guid><category><![CDATA[Security]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[Developer Tools]]></category><category><![CDATA[securityawareness]]></category><dc:creator><![CDATA[Keshav Malik]]></dc:creator><pubDate>Wed, 07 Dec 2022 06:09:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1670393249360/7Nw9vdAp5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the past, the development of software was something that required a lot of effort and resources. Basically, every piece of code was developed in-house, and code reuse was quite limited. The situation is now the opposite. Open-source packages are so widely used that they make up the bulk of the total amount of software produced by passionate hobbyists and virtually all the software professionals in tech companies. The convenience of reusing and fine-tuning components made open-source is just too strong for most software engineers to ignore it and keep "reinventing the wheel".</p>
<p>To get a better idea of how big open source has become, we have some recent insights: according to a <a target="_blank" href="https://www.gartner.com/en/documents/3971011">survey</a> from Gartner, over 90% of the respondents stated that they rely on open source components. In another <a target="_blank" href="https://www.synopsys.com/content/dam/synopsys/sig-assets/reports/rep-ossra-2021.pdf">report</a> from Synopsis, 98% of the audited codebases contained at least one open-source component, and 75% of the source code came from open-source. The report also noted that 85% of the audited codebases contained components "more than four years out of date".</p>
<p>This last data reveals the growing concern about the reliability and security of all this open-source material found in private code bases. Packages that are not maintained anymore cannot be patched for recently discovered vulnerabilities. Therefore it's become critical for organizations to be able to inventory open-source components and assess their vulnerabilities, making the use of software composition analysis mandatory. But not all SCA tools are created equal.</p>
<p>This blog post will provide eight factors to consider when choosing an SCA tool.</p>
<h2 id="heading-what-is-sca-software-composition-analysis">What is SCA (Software Composition Analysis)?</h2>
<p>SCA is the process of analyzing an application's dependencies to determine if it is affected by known security vulnerabilities. Organizations can more effectively manage security risks by understanding the dependencies between components.</p>
<p>SCA can be performed either manually or using automated tools. Manual SCA is not scalable as the engineers must constantly check a vulnerability database such as <a target="_blank" href="https://nvd.nist.gov/">NVD</a> (National Vulnerability Database, maintained by NIST) and then compare the vulnerable versions with their existing dependencies. Much more efficient is to use automated SCA scanning tools, which can be triggered manually or integrated into the CI/CD pipeline for continuous checks.</p>
<h2 id="heading-importance-of-software-composition-analysis">Importance of Software Composition Analysis</h2>
<p>SCA is integral to application security, as it helps identify and mitigate risks associated with using third-party components. SCA can help identify vulnerabilities in third-party components that attackers could exploit. It can also help track the versions of third-party components and ensure that they are up to date. By keeping track of the components used in an application, SCA can also help ensure compliance with license and security policies.</p>
<p>In short, SCA is an essential part of the code security toolkit, focused on third-party components.</p>
<h2 id="heading-how-is-sca-different-from-sast">How is SCA different from SAST?</h2>
<p>SAST is a software testing technique that involves analyzing the source code of a software application to identify potential security vulnerabilities such as injection attacks, cross-site scripting (XSS), improper error handling, and insecure use of cryptographic functions.</p>
<p>SAST aims to identify security vulnerabilities early in the software development cycle to mitigate them before the application is compiled and deployed.</p>
<p>While SAST is an analysis technique used to check for known vulnerabilities in source code, SCA is used to scan dependencies for security vulnerabilities and license issues.</p>
<p>Both are usually performed pre-build (against source code), or post-build (against binaries), as they don't require an application's execution to identify potential vulnerabilities. Both are equally important in ensuring the security of a software application.</p>
<h1 id="heading-how-to-choose-an-sca-tool">How to Choose an SCA tool?</h1>
<p>The many SCA tools on the market today can make it hard to decide which is the right one for your needs. To help you select the right one, we have curated a list of 9 things you should look out for in an SCA tool:</p>
<h2 id="heading-1-language-support">1. Language Support</h2>
<p>When opting for an SCA tool, it's vital to check what all languages are supported by the tool. Software composition analysis is language, end even ecosystem-dependent (package managers, build system, etc.): for instance, most SCA tools rely on lock files such as <code>package-lock.json</code> or <code>Pipfile.lock</code> to find dependencies and their respective versions. So you need to be careful here.</p>
<h2 id="heading-2-accessible-to-usedeveloper-friendliness">2. Accessible to Use/Developer Friendliness</h2>
<p>The SCA tool you choose should make your life easier, not harder. It should be intuitive and easy to use so that you can focus on your work, not on learning the tool. It should also be developer friendly so that you can easily integrate it into your existing development process. Also, it should be scalable to grow with your organization.</p>
<p>The vendor should also have proper technical documentation available for the developers and having technical support for the tool is always a plus.</p>
<h2 id="heading-3-support-for-binary-scanning">3. Support for Binary scanning</h2>
<p>When looking for a Software Composition Analysis (SCA) tool, choosing one that supports the scanning of binary files is essential. Many SCA tools don't support this type of scanning, which can leave vulnerabilities in the binaries used by the developers unchecked.</p>
<p>Scanning binary files such as wheel files(.whl) are essential because it can find vulnerabilities that would otherwise be missed by scanning the dependencies. If you are not doing binary scanning used by your developers, you are not getting the complete picture of your code's security.</p>
<h2 id="heading-4-direct-vs-transitive-dependencies">4. Direct vs. Transitive Dependencies</h2>
<p>There are two types of dependencies in software development: direct and transitive.</p>
<p>A direct dependency is when one piece of software directly depends on another piece of software. For example, if software A directly uses software B, then A has a direct dependency on B. Conversely if software A uses software B, and software B uses software C, then A has a transitive dependency on C.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1670393236316/QaX6sM7P4.png" alt /></p>
<p>The SCA tool should be able to provide you with the information if the vulnerability is in the direct dependency or transitive dependency. This is important because both types of dependencies can pose a security threat to a software project.</p>
<h2 id="heading-5-false-positives-false-negatives">5. False positives / False negatives</h2>
<p>If you are not familiar with the concept of false positives and false negatives, you should read this article about <a target="_blank" href="https://blog.gitguardian.com/secrets-detection-accuracy-precision-recall-explained/">accuracy, precision, and recall</a>.</p>
<p>In a nutshell, false positives are vulnerabilities wrongly flagged as such by the tool, and false negatives are genuine vulnerabilities that the detection tool silently skipped. This is an important factor to consider when choosing a software composition analysis tool because false positives can lead to wasted time and resources.</p>
<p>Developers may spend a significant amount of time manually reviewing and investigating these results, even though most are not security threats. This (also known as "alert fatigue") can be frustrating for developers and decrease their trust in the tool, potentially leading them to ignore or not use the tool as frequently as they otherwise would.</p>
<p>The numbers reported by vendors can be challenging to verify. The best way to ensure that an SCA tool can accurately identify security threats while minimizing the number of false positives is to test it (for free, when possible).</p>
<h2 id="heading-6-webhooks-andamp-api-support">6. Webhooks &amp; API Support</h2>
<p>When looking for an SCA tool, it's essential to check if the tool has proper API and webhook support so that you can easily integrate it into your CI/CD pipeline.</p>
<p>Having proper API and webhook support will allow you to automate SCA scanning as part of your CI/CD process, which will help ensure that your applications are always up-to-date and compliant with security standards. Without proper API and webhook support, you may have to manually trigger SCA scans, which can lead to delays in your pipeline.</p>
<h2 id="heading-7-rich-vulnerability-database">7. Rich Vulnerability Database</h2>
<p>A good SCA vendor should have a rich vulnerability database to detect vulnerabilities in your open-source packages. Such a database would enable the SCA vendor to provide you with customized alerts and recommendations on the best way to fix the identified vulnerabilities.</p>
<p>In addition, the SCA vendor should have a team of expert analysts who can help you understand the nature of the vulnerabilities and their potential impact on your organization in case you need any support.</p>
<h2 id="heading-8-time-to-onboard-new-cves">8. Time to Onboard New CVEs</h2>
<p>SCA tools are used by many organizations to keep track of vulnerabilities and potential security risks. It's essential to check how much time the SCA tool takes to onboard new CVEs on their platform from the vulnerability database. This allows organizations to plan for and respond to new security risks promptly. Additionally, it helps to ensure that SCA tools are up-to-date and provide accurate information about the latest security threats.</p>
<h2 id="heading-9-detailed-reportingremediation">9. Detailed Reporting/Remediation</h2>
<p>The scanning should provide detailed reporting that helps the security team understand the scan results of the open-source packages. The report should include a list of all the packages that were scanned, as well as the results of the scan, including</p>
<ul>
<li><p>Vulnerability description</p>
</li>
<li><p>CVSS score</p>
</li>
<li><p>CVSSv3 score</p>
</li>
<li><p>Version impacted</p>
</li>
</ul>
<p>The SCA tool should also provide proper remediation steps so that the developers can fix the issues.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Open source has become the norm in the software development world, with nearly 80% of companies using open-source software in some form or another. For many companies, open source is the preferred choice for software development due to its flexibility, cost-effectiveness, and vast ecosystem of available tools and resources.</p>
<p>However, with the increasing popularity of open source, there is also an increase in the number of vulnerabilities of open-source packages. This can create several risks and challenges for companies, including vulnerabilities in developed applications, licensing issues, and potential security breaches.</p>
<p>Having SCA tools in your build and deployment pipeline can help you avoid security risks that might arise from any open-source dependency. You should now be more informed about the important factors to consider before selecting such as tool.</p>
]]></content:encoded></item><item><title><![CDATA[Best practices for managing developer teams in GitHub Orgs]]></title><description><![CDATA[Are you looking for ways to manage your developer team better? GitHub Orgs is a great way to keep track of repositories, branches, and collaborators all in one place. In this article, we'll share some best practices for managing developer teams in Gi...]]></description><link>https://blog.theinfosecguy.xyz/best-practices-for-managing-developer-teams-in-github-orgs</link><guid isPermaLink="true">https://blog.theinfosecguy.xyz/best-practices-for-managing-developer-teams-in-github-orgs</guid><category><![CDATA[GitHub]]></category><category><![CDATA[Developer]]></category><category><![CDATA[development]]></category><category><![CDATA[agile]]></category><dc:creator><![CDATA[Keshav Malik]]></dc:creator><pubDate>Thu, 27 Oct 2022 17:14:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1666890853018/rOxoFU5sC.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Are you looking for ways to manage your developer team better? GitHub Orgs is a great way to keep track of repositories, branches, and collaborators all in one place. In this article, we'll share some best practices for managing developer teams in GitHub Orgs.</p>
<p>There's a lot to love about GitHub, and the organizational structure it can give you is definitely one of them. When you share your code with other developers, make it public, or collaborate with a large team (or even a small one), the circle expands faster than you would imagine. Like it or not, a managed hierarchy of access and well-thought rules become imperative for the sustainability and security of your projects.</p>
<p>What could go wrong if you do not manage access? It's a legitimate question considering you trust the people you collaborate with. Well, all it takes is an honest intern who rewrites the history in your master branch to wreak havoc. Let us say it is safe to have a managed organizational structure, and that's what we'll talk about.  </p>
<p>In this blog, I will guide you through the best practices for managing developer teams in GitHub Orgs and provide recommendations to help you secure your GitHub organization.</p>
<h2 id="heading-what-is-an-organization-in-github">What is an organization in GitHub?</h2>
<p>A GitHub organization is a shared platform where you can put one or more repositories and share controlled access with members and collaborators who can perform specific tasks. These organizations can be companies, non-profit organizations, some coalitions, or independent developers working together on a project for fun. An unlimited number of people can collaborate in an organization across multiple projects. </p>
<p>Usually, an organization has five levels of role-based permissions</p>
<ul>
<li><p>Owner: has complete control of the organization along with full administrative access. They can determine the team's access level to the project code.</p>
</li>
<li><p>Billing manager: can manage payment settings for the organization. This includes setting up payment methods, managing subscriptions, and viewing invoices.</p>
</li>
<li><p>Member:  is granted role-based access to control what they can see and do within the organization. Depending on their role, they may access the repositories or projects.</p>
</li>
<li><p>Moderator: have all the permissions granted to members by default. On top of that, they can block or unblock outside collaborators, set interaction limits, and hide comments on public repositories that belong to the organization.</p>
</li>
<li><p>Outside collaborator: a contractual member who's granted access to one or more repositories to perform specific tasks but doesn't have the full array of permissions granted to the members.</p>
</li>
</ul>
<h2 id="heading-what-is-a-team-in-github">What is a team in GitHub?</h2>
<p>Teams are groups of members that reflect the organization's structure. The teams are maintained by organization owners and team maintainers who can manage the level of access granted to a team and add or remove members. Teams have pages where you can see the members, child teams, the team profile picture, etc.</p>
<h3 id="heading-managing-a-teams-access-to-repositories-in-github">Managing a team's access to repositories in GitHub</h3>
<p>The owners can give a team access to a repository, remove the access, or modify the permission level to a specific repository based on the need.
If a team has direct access to a repository, the access can be simply removed. However, if a team has inherited access from a parent team, then the maintainers have to remove the access for the parent team to remove access for the child team.</p>
<p><img src="https://blog.gitguardian.com/content/images/2022/10/Frame-67.png" alt /></p>
<h2 id="heading-8-best-practices-for-managing-teams-in-github">8 Best Practices for Managing Teams in GitHub</h2>
<p>Now that we have somewhat established organizations and teams in GitHub let's jump right into the practices that make it easier to manage teams safely and sustainably.</p>
<h3 id="heading-configure-the-organization">Configure the Organization</h3>
<p>Creating an organization on GitHub is extremely simple; it takes just a few clicks. But you should take the time to configure the organization based on the group's specific needs. This could mean restricting access to certain repositories, setting up review cycles, or modifying other settings to strengthen the organization's security. This will help to keep things organized and make it easier for team members to find the information they need.</p>
<h3 id="heading-one-branch-for-each-feature-or-bug">One Branch for Each Feature or Bug</h3>
<p>One of the key advantages of a GitHub organization is allowing an unlimited number of developers to work on different projects simultaneously. Having a branch for each bug or feature helps you make the most out of this advantage, allowing multiple people to work on various features without worrying about overwriting the code written by someone else. This also keeps things well organized.</p>
<h3 id="heading-create-nested-teams">Create Nested Teams</h3>
<p>As an organization owner, you can create child teams or nested teams that inherit the permissions from their parent teams. It simplifies access management, as adding or removing permissions for the parent teams automatically means doing the same for the child teams. </p>
<p>When working with a large number of groups, having nested teams simplify communication.
Nested teams can also be given different permissions than their parent teams so that you can tailor the team's access to your organization's needs.</p>
<h3 id="heading-assign-code-owners">Assign Code Owners</h3>
<p>The success of a project relies heavily on code reviews. Code owners are a special type of GitHub user responsible for reviewing and approving code changes in a repository. Code owners can be assigned to specific files or directories and will be notified whenever a change is made to those files. This makes pull requests safer, removes the confusion pertaining to ownership and reviews, and ensures the smooth functioning of a team.</p>
<h3 id="heading-rebasing-the-feature-branches">Rebasing the Feature Branches</h3>
<p>As we have discussed earlier, creating a branch for each feature or bug is a good practice. But if a team is working on a bunch of features simultaneously, it creates a complicated graph of branches that becomes very difficult to track. To avoid that, the ideal practice is to rebase the feature branches with the master branch.</p>
<p><a target="_blank" href="https://www.atlassian.com/git/tutorials/rewriting-history/git-rebase">Rebasing</a> can help resolve merge conflicts more efficiently and make it easier to track changes and keep your codebase up to date.</p>
<h3 id="heading-squash-commits-before-merging">Squash Commits Before Merging</h3>
<p>Commits are like milestones in the journey of a Git project. Squashing commits is a way of rewriting the commit history before you share it with your team. It keeps the commit history clean and makes it easier to associate a bug with a specific commit when it comes to testing or debugging.</p>
<h3 id="heading-setup-pre-merge-andamp-post-merge-jobs-with-github-repositories">Setup Pre-Merge &amp; Post-Merge Jobs with GitHub Repositories</h3>
<p>If you're using GitHub for your project development, you can easily set up pre-merge and post-merge jobs to run automatically on your repositories.</p>
<p>This also helps to ensure that the code integrates properly and that any potential conflicts are resolved before they cause problems. Pre-merge jobs can be used to run tests and verify that the code compiles correctly. Post-merge jobs can be used to deploy the code to a staging environment for further testing.</p>
<h3 id="heading-use-secret-scanning-tools">Use Secret Scanning Tools</h3>
<p>Secret scanning tools like GitGuardian or <a target="_blank" href="https://github.com/zricethezav/gitleaks">gitleaks</a> can help you avoid accidentally leaking secrets like API keys and passwords through your GitHub repositories. These tools work by scanning your repositories and pull requests for potentially sensitive information and then alerting you so you can take action to remove or protect the information.
You can install the GitGuardian App through the GitHub Marketplace for free on public repositories <a target="_blank" href="https://github.com/marketplace/gitguardian">here</a>.</p>
<p>Using a secret scanning tool is a good first step in preventing accidental leaks, but it's also important to be aware of the potential risks and to review your code regularly to ensure that no sensitive information is accidentally left exposed.</p>
<h3 id="heading-track-progress-using-github-projects">Track Progress using GitHub Projects</h3>
<p>It is essential to keep track of team progress. This can be done by creating a <a target="_blank" href="https://docs.github.com/en/issues/planning-and-tracking-with-projects/learning-about-projects/about-projects">GitHub project board</a> and adding issues and milestones. This feature allows you to create Kanban-style boards for your repositories to see what's being worked on and what is still pending. You can also add notes and tags to your cards to keep all the relevant information in one place. Tracking progress using GitHub Projects is a great way to keep your project organized and on track.</p>
<h2 id="heading-best-practices-to-secure-your-github-organization-at-a-glance">Best practices to secure your GitHub Organization at a glance</h2>
<p>To keep your GitHub Organization secure, it is essential to follow best practices. Some of these best practices include:</p>
<h3 id="heading-backup-andamp-restore-for-your-repos">Backup &amp; restore for your repos</h3>
<p>As a best practice, it is always recommended that you have a backup and recovery plan for critical repositories and ever-changing metadata. This will help ensure that you can recover your data in the event of a disaster and that your metadata is always up-to-date.</p>
<h3 id="heading-supervise-access-controls">Supervise access controls</h3>
<p>One of the most crucial security steps is setting access controls on an as-needed basis. Make sure that no one has more permissions than they need to have. This will help to prevent unauthorized access to sensitive information. You should also have a process in place for revoking access when someone no longer needs it.</p>
<h3 id="heading-mfa-for-all">MFA for all</h3>
<p>Enforce multi-factor authentication for all members of the GitHub organization, moderators &amp; billing managers. MFA (multi-factor authentication) adds an extra layer of security to your account by requiring you to enter a code from your mobile phone or another device in addition to your password. This makes it much harder for threat actors to gain access to your account, even if they have your password.</p>
<h3 id="heading-security-policies">Security policies</h3>
<p>Organizations on GitHub have several different <a target="_blank" href="https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/managing-security-and-analysis-settings-for-your-organization">security settings</a> that can be adjusted to fit the organization's needs. It is essential to review these settings regularly and audit your member's activity to ensure that your organization's data is safe.</p>
<h2 id="heading-to-sum-it-up">To sum it up</h2>
<p>GitHub organizations are fantastic if you can maintain a few habits and imbibe some practices into the way your teams function. The responsibility is shared between the owners and the team members. As the owner, you can create nested teams, set security policies, and assign code owners to make things easier. Then if the team members can pull their share of the weight by being responsible for squashing the commits, rebasing the branches, and testing code, everything falls into place.</p>
]]></content:encoded></item><item><title><![CDATA[How to Efficiently Merge Pull Requests using Mergify?🧑‍💻]]></title><description><![CDATA[Shopify is a large-scale eCommerce platform that makes heavy use of code commits and merges to keep its operation running smoothly. On a typical day, Shopify will make around 40 code changes and merge 400 commits into its master codebase. This level ...]]></description><link>https://blog.theinfosecguy.xyz/how-to-efficiently-merge-pull-requests-using-mergify</link><guid isPermaLink="true">https://blog.theinfosecguy.xyz/how-to-efficiently-merge-pull-requests-using-mergify</guid><category><![CDATA[agile]]></category><category><![CDATA[Developer]]></category><category><![CDATA[Productivity]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Keshav Malik]]></dc:creator><pubDate>Fri, 12 Aug 2022 14:04:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1660313024219/Gl-xYmCCQ.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Shopify is a large-scale eCommerce platform that makes heavy use of code commits and merges to keep its operation running smoothly. On a typical day, Shopify will make around 40 code changes and merge 400 commits into its master codebase. This level of activity would be unmanageable for most companies, but Shopify and most tech giants like Uber and AWS have put in place several systems and processes to help them manage and collaborate on such a large scale.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1660312913385/Kd-nB_Vod.jpg" alt="Git Merge" /></p>
<p>One such way is using Merge Queues. Merge Queue allows developers to manage and collaborate on code changes on a large scale.</p>
<p>Merge Queues are a crucial part of how most tech companies are able to manage and collaborate on code at such a large scale. Merge Queues allow developers to work together on code changes without worrying about breaking the production, merge conflicts, or waiting for PR to be merged.</p>
<h2 id="heading-understanding-the-problem">Understanding the Problem</h2>
<p>Engineering teams are tasked with developing new features across multiple branches to keep many different products in step. This means that there is a lot of merging to do. When many engineers are working concurrently, there are likely to be many branches and PRs; merging these branches can lead to various conflicts and even break the application or production environment. </p>
<p>Most companies use CI to prevent such issues. But even with CI in place, if you don't manage your PRs correctly, you may break the prod. But how? Let me explain this with an example.</p>
<p>You asked your team of developers to add X features to the application. They started working on it based on what you assigned them by creating their feature branch. One of the developers completed the task and created the PR, and CI checks also ran successfully. Meanwhile, the other developer also changed one of the files affecting the first PR and created his PR (CI ran successfully again🟢).</p>
<p>The senior developer started looking at both the PRs and thought of merging as CI passed, and everything was good. The senior dev merged the second PR first, which changed in the file affecting the other PR. As the CI was already 🟢, he merged the other one too. You know what happened next. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1660312946586/6TI4xrAHZ.jpg" alt="The Problem" /></p>
<h2 id="heading-how-to-overcome-the-problem">How to Overcome the Problem? 💡</h2>
<p>The solution to this problem is Merge Queues that automate this tedious task for you by ensuring that before merging, the PRs are up-to-date with their respective base branches. And if you have a CI process, it will pick up these PRs again and rerun the jobs on the new code.</p>
<p>So, GitHub must be offering this. Not quite ❌. GitHub provides a built-in merge queues feature; however, as per their official <a target="_blank" href="https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue">documentation</a>, it is currently in limited public beta and thus not generally available to all. On the other hand, GitLab calls this feature <a target="_blank" href="https://docs.gitlab.com/ee/ci/pipelines/merge_trains.html">Merge Trains</a> and is available only for premium users.</p>
<p>If you use GitHub and have been reviewing PRs even for a while now, you know that there are certain kinds of PRs that you don't even need to thoroughly review based on whatever factors like saying a PR is good to be merged if the PR:</p>
<ul>
<li>just adds files and does not modify or delete any of the existing files </li>
<li>modifies just the README.md file </li>
<li>is approved by a senior developer 🧑‍💻</li>
</ul>
<p>This is where <a target="_blank" href="https://www.mergify.com/?utm_source=devto&amp;utm_medium=social&amp;utm_campaign=Keshav">Mergify</a> comes in 🚀. Mergify enables you to do that and a lot more. It's a SaaS integration that connects with GitHub repositories to automate and assist with prioritizing, queuing, and merging PRs. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1660312965200/3bLxBLPLY.jpg" alt="Mergify Everywhere" /></p>
<p>Here are some more use cases for you that can be achieved with Mergify apart from condition-based automated merging:</p>
<ol>
<li>Rebase the source branch of PRs</li>
<li>Label and assign to fellow team members</li>
<li>Delete the head branches upon PR merge</li>
</ol>
<p>Although there are various options in the market for merge queues like MergeQueue, Mergify stands out as not just a merge queue offering but also as a process automation solution. </p>
<p>Some of the benefits of using Mergify over <a target="_blank" href="https://mergify.com/vs/mergequeue">MergeQueue</a> and other similar alternatives include:</p>
<ol>
<li>Offers time-saving features such as speculative checks and batch pull requests that positively affect the merge time.</li>
<li>Offers the ability to set up multiple queues in which you can sort, order, and prioritize your PRs based on condition checks and how your processes work.</li>
<li>Offers not just safe code merging capability but a complete automated approach towards dealing with multiple collaborators for your codebase.</li>
<li>Offers community support and dedicated customer success manager on paid plans where you also get premium features such as priority queues, random request reviews, private deployments, and much more.</li>
</ol>
<h2 id="heading-how-to-setup-and-install-mergify">How to Setup and Install Mergify? 😁</h2>
<p>Now when we have a fair understanding of what Mergify is and how it can help us, let's dive into how you can get started with Mergify.</p>
<ul>
<li>Have yourself signed into your GitHub account.</li>
<li>Have a public repository ready to be connected with Mergify. (private repositories are supported in paid plans) </li>
<li>Head to Mergify SignUp and sign in via GitHub, and you can choose to let Mergify connect to all your repositories or select a few, similar to how GitHub apps work.</li>
</ul>
<h2 id="heading-getting-started-with-mergify">Getting Started with Mergify 🚀</h2>
<p>Now when you're all signed up and Mergify connected to your GitHub repository, let's walk through a couple of examples to see how Mergify can solve our problems.</p>
<p>Mergify's configs have a pretty simple structure. It has a list of conditions that, when become true with respect to any of our PRs, the mentioned actions shall take place. </p>
<p>We can define multiple pull request rules that Mergify will check our PRs against but for the sake of simplicity of this article, let's stick to the simple ones that will help a larger audience get started with Mergify.</p>
<p>To set up a config, you need a file <code>.mergify.yml</code> in the root of your directory that will tell Mergify what to do with the PRs. What we'll have in the config editor when we open it up for the first time will be a very basic initial configuration that the Mergify config editor loads up by default once a repository is connected. </p>
<p>What's nice about Mergify is that you can create a PR from the Mergify Dashboard itself that'll create a .mergify.yml file for you in your repo. Even if you feel it's too soon and you need to test it before committing stuff, then there's a test option available within the config editor where you can test your config against a particular PR to test out the config. It also acts as a validation of your config schema.</p>
<p>Let's go through the same initial config where we've added just another condition.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">pull_request_rules:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Automatic</span> <span class="hljs-string">merge</span> <span class="hljs-string">on</span> <span class="hljs-string">approval</span>
    <span class="hljs-attr">conditions:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"#approved-reviews-by&gt;=1"</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"author=theinfosecguy-example"</span>
    <span class="hljs-attr">actions:</span>
      <span class="hljs-attr">merge:</span>
        <span class="hljs-attr">method:</span> <span class="hljs-string">merge</span>
</code></pre>
<p>Given the minimal config, translating this into simpler terms means that whenever a PR has either 1 or more approvals just go ahead and merge the PR.</p>
<p>In a PR in our example repo, as shown below, the PR was authored by <code>@theinfosecguy-example</code> and the moment the PR got approved by a collaborator, the Mergify bot went ahead and merged the PR as post the approval this PR matched all the conditions mentioned in our pull request rules in the config, as mentioned above.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i1ggswtkqr8cu3wpwv32.png" alt="Mergify Everywhere" /></p>
<p>You can refer to <a target="_blank" href="https://docs.mergify.com/conditions/#conditions">Conditions — Mergify documentation</a> to get a hold of all the conditions Mergify can work with which you can further combine as per your teams’ needs.</p>
<p><a target="_blank" href="https://www.mergify.com/?utm_source=devto&amp;utm_medium=social&amp;utm_campaign=Keshav">Mergify</a> will take care of your simple checks freeing a large chunk of your time to focus on the more challenging PRs where merge conflicts arise and PRs with outdated base branches require your input.</p>
<p>Here’s another example where we have multiple PRs that desire to update a single file meaning that the base branch of the second PR will be outdated once the first PR is merged but Mergify is here to save the day.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vsq5ub6hp1sc47ljzym5.png" alt="Mergify Dashboard" /> </p>
<p>Firstly we have defined a queue, you can define multiple as per your requirement, and then we have to define pull request rules. Here’s the config for your reference.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">queue_rules:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">default</span>
    <span class="hljs-attr">conditions:</span> []
<span class="hljs-attr">pull_request_rules:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">merge</span> <span class="hljs-string">using</span> <span class="hljs-string">the</span> <span class="hljs-string">merge</span> <span class="hljs-string">queue</span>
    <span class="hljs-attr">conditions:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"#files=1"</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"author=theinfosecguy-example"</span>
    <span class="hljs-attr">actions:</span>
      <span class="hljs-attr">queue:</span>
        <span class="hljs-attr">name:</span> <span class="hljs-string">default</span>
</code></pre>
<p>In this particular config, we have set up a queue named "default" and the conditions say that if the PR modifies one single file and is authored by a specific user, then send the PR to the "default" merge queue to be further merged.</p>
<p>Let's take another example to understand better the automated PR management in a team of multiple collaborators where say; you have a senior Python developer and a DevOps team to be looped in regarding security-related tasks.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">queue_rules:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">default</span>
    <span class="hljs-attr">conditions:</span> []
<span class="hljs-attr">pull_request_rules:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">assign</span> <span class="hljs-string">PRs</span> <span class="hljs-string">with</span> <span class="hljs-string">Python</span> <span class="hljs-string">files</span> <span class="hljs-string">modified</span> <span class="hljs-string">to</span> <span class="hljs-string">theinfosecguy-example</span>
    <span class="hljs-attr">conditions:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">files~=\.py$</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">-closed</span>
    <span class="hljs-attr">actions:</span>
      <span class="hljs-attr">assign:</span>
        <span class="hljs-attr">add_users:</span>
          <span class="hljs-bullet">-</span> <span class="hljs-string">theinfosecguy-example</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">ask</span> <span class="hljs-string">the</span> <span class="hljs-string">security</span> <span class="hljs-string">team</span> <span class="hljs-string">to</span> <span class="hljs-string">review</span> <span class="hljs-string">security</span> <span class="hljs-string">labeled</span> <span class="hljs-string">PR</span>
    <span class="hljs-attr">conditions:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">label=security</span>
    <span class="hljs-attr">actions:</span>
      <span class="hljs-attr">request_reviews:</span>
        <span class="hljs-attr">teams:</span>
          <span class="hljs-bullet">-</span> <span class="hljs-string">"@myorg/devops"</span>
</code></pre>
<p>This above-mentioned config has two rules, the first one will look for open PRs that modify any files with <code>.py</code> extension and assign the PR to <code>theinfosecguy-example</code> whereas the second rule states that if a PR is labeled as “security” then request reviews from the “devops” team from your GitHub organization which you’d anyway do if even if not automated.</p>
<p>Having a look at their <a target="_blank" href="https://docs.mergify.com/'">documentation</a>, Mergify can cater to many use cases with its powerful condition-based automation configurations.</p>
<h2 id="heading-conclusion">Conclusion 🙌</h2>
<p>All merge queues do is avoid merging outdated PRs to prevent merging broken pull requests and extend that functionality. Mergify also automates DevOps operations, prioritization, queuing, and condition-based automatic merges. You can have multiple queues, multiple condition checks, more advanced checks with logical and grouping, and whatnot. </p>
<p>Although <a target="_blank" href="https://mergify.com/pricing">Mergify</a> requires a paid subscription to set up multiple queues and connect to private repositories, it is free and offers basic open-source project features. They also have a 14-day free trial on their paid plans if you want to check out the premium features. </p>
<p>Check out <a target="_blank" href="http://www.mergify.com/?utm_source=devto&amp;utm_medium=social&amp;utm_campaign=Keshav">Mergify</a>!</p>
]]></content:encoded></item><item><title><![CDATA[3 Security Best Practices for React JS 🙌]]></title><description><![CDATA[ReactJS is a front-end development JavaScript framework that has become very popular recently. One of the reasons it is popular is its ability to allow developers to create highly interactive user experiences. 
Security is always a concern, and React...]]></description><link>https://blog.theinfosecguy.xyz/3-security-best-practices-for-react-js</link><guid isPermaLink="true">https://blog.theinfosecguy.xyz/3-security-best-practices-for-react-js</guid><category><![CDATA[React]]></category><category><![CDATA[Security]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Keshav Malik]]></dc:creator><pubDate>Mon, 06 Jun 2022 18:24:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1654539691243/JsNAqf4PW.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a target="_blank" href="https://reactjs.org/">ReactJS</a> is a front-end development JavaScript framework that has become very popular recently. One of the reasons it is popular is its ability to allow developers to create highly interactive user experiences. </p>
<p>Security is always a concern, and ReactJS is no different. If security is handled properly, ReactJS can be a great framework for developing web and mobile applications (using react-native). </p>
<p>This blog will list 3 best practices for ReactJS projects that can help you avoid security vulnerabilities.</p>
<h2 id="heading-what-is-reactjs">What is ReactJS?</h2>
<p>React is a front-end JavaScript library developed by Facebook. This library is used for building user interfaces and allows you to create reusable components.</p>
<p>The Facebook team built it because they needed a way to handle DOM updates while the browser was still rendering a page, so the user wouldn't notice the page was still loading. React has become more and more popular over the last few years. A lot of people love it for its sheer simplicity and its speed.</p>
<h2 id="heading-why-is-secure-coding-important">Why is Secure Coding Important?</h2>
<p>Every technology has its own set of security vulnerabilities. The big question is, are you securely using them? You may have heard the term "secure coding" before, but what does it mean? </p>
<p>Secure coding refers to the practice of writing code that is immune to attacks. It is a subset of software security that refers to all aspects of a software system, including but not limited to its architecture and implementation, that prevent malicious parties from being able to access the software for malicious purposes. </p>
<p>Today, most applications are vulnerable to the <a target="_blank" href="https://owasp.org/www-project-top-ten/">OWASP top 10 vulnerabilities</a>, and React applications are no different. If you don't know what these vulnerabilities are, you should probably look at them on the OWASP official website. </p>
<p>No matter what technology you use, you'll need to know how to implement secure coding practices. Let’s take a look at 3 security best practices for your React project that you can adopt today. </p>
<h2 id="heading-3-security-best-practices-for-reactjs">3 Security Best Practices for ReactJS</h2>
<p>Everyone wants a secure application. But how do we achieve this? We need to do a couple of things to make the React application secure from the ground up. Let's dive in.</p>
<h3 id="heading-1-avoid-using-dangerouslysetinnerhtml">1. Avoid using dangerouslySetInnerHTML</h3>
<p>Quite simply, dangerouslySetInnerHTML is a property you can use on HTML elements in a React application to set their content programmatically. But why is dangerouslySetInnerHTML dangerous?</p>
<p>If you are not careful with the HTML you are passing in, you could open yourself up to a cross-site scripting (XSS) attack. Let’s understand this using an example.</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">XSS</span>(<span class="hljs-params"></span>) </span>{
  const vulnerableHTML <span class="hljs-operator">=</span> `
    <span class="hljs-operator">&lt;</span>div<span class="hljs-operator">&gt;</span>
        Hello, world<span class="hljs-operator">!</span>
        <span class="hljs-operator">&lt;</span>img src<span class="hljs-operator">=</span><span class="hljs-string">"abc"</span> onerror<span class="hljs-operator">=</span><span class="hljs-string">"alert('XSS')"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>div<span class="hljs-operator">&gt;</span>`;

  <span class="hljs-keyword">return</span> (
    <span class="hljs-operator">&lt;</span>div<span class="hljs-operator">&gt;</span>
      This <span class="hljs-keyword">is</span> a XSS Vulnerable Component <span class="hljs-keyword">using</span> <span class="hljs-title">dangerouslySetInnerHTML</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-title">div</span> <span class="hljs-title">dangerouslySetInnerHTML</span><span class="hljs-operator">=</span>{{ <span class="hljs-title">__html</span>: <span class="hljs-title">vulnerableHTML</span> }}<span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">div</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">div</span><span class="hljs-operator">&gt;</span>
  );
}

export default XSS;
</code></pre><p>In the code mentioned above, we use dangerouslySetInnerHTML in a React Component. Still, if you carefully look at the HTML code stored in the vulnerable HTML variable, you’ll understand that when the stored HTML renders, this will make the application vulnerable to XSS (Cross-Site Scripting). But what exactly is XSS, and how can you prevent it?</p>
<p>Cross-site scripting (XSS) attacks inject malicious scripts into otherwise benign and trusted websites. Attackers can use XSS to bypass access controls such as the same-origin policy.</p>
<p>To prevent your application from XSS attacks, you must sanitize your data before passing it to dangerouslySetInnerHTML. Various <a target="_blank" href="https://www.npmjs.com/package/dompurify">NPM packages</a> are available that can help you do so, or you can write your regex to sanitize the data.</p>
<p><strong><em>Also Read: <a target="_blank" href="https://dev.to/theinfosecguy/how-to-fix-clickjacking-on-nginx-server-in-6-simple-steps-2lbp">How to Fix Clickjacking on NGINX Server in 6 Simple Steps</a>🔥</em></strong></p>
<h3 id="heading-2-avoid-hardcoding-secrets">2. Avoid Hardcoding Secrets</h3>
<p>If you use React in your application, you most likely have some secret information that you don’t want to expose to the internet. For example, you may have a database URL, API key, or password. </p>
<p>The common approach is to store the secrets in environment variables and then access them in the application using process.env.SECRET_KEY. Environment variables stored in .env are a part of the build and are publicly accessible. You can see that in your browser by going to the React Dev Tools.</p>
<pre><code><span class="hljs-attr">AWS_ACCESS_KEY</span>=<span class="hljs-string">""</span>
<span class="hljs-attr">AWS_SECRET_KEY</span>=<span class="hljs-string">""</span>
<span class="hljs-attr">AWS_REGION</span>=<span class="hljs-string">""</span>
</code></pre><p>One of the ways to solve this issue is to store the keys on the server and then retrieve them as per your needs. But this is not a suitable way to do this. The best way is to pass the environment variable directly to the server wherever you host your application, like EC2. </p>
<p>Not just this, most frontend deployment platforms, such as Vercel, Netlify, etc., allow you to add environment variables directly through their platform.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654538718201/HY2CQtiyn.png" alt="3-1.png" class="image--center mx-auto" /></p>
<h3 id="heading-3-disable-generatesourcemap-in-build-script">3. Disable GENERATE_SOURCEMAP in Build Script</h3>
<p>If you have a React application that you have deployed on any front-end platform or any server and you have not updated the build script from the package.json file, you might be disclosing your application's source code to the internet.</p>
<p>You can check this by going to the Source tab and clicking on your website name. Here’s how it looks.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654539064467/MV2u9fjH6.png" alt="image.png" class="image--center mx-auto" /></p>
<p>As you can see in the above image, the whole source code of the application is disclosed; this vulnerability is known as Source Code Disclosure.</p>
<p>To fix this issue, update the build script to:</p>
<pre><code><span class="hljs-string">"build"</span>: <span class="hljs-string">"GENERATE_SOURCEMAP=false react-scripts build"</span>
</code></pre><p>Learn more about <a target="_blank" href="https://create-react-app.dev/docs/advanced-configuration/">GENERATE_SOURCEMAP</a></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The security industry is fast-paced, so it’s difficult to stay up to date with the latest news and threats. As a developer, it’s important to keep up with the industry and be aware of the latest trends and threats. I’ve explained three best practices to avoid security vulnerabilities in the ReactJS application in this post.</p>
<p>If you have any questions or concerns about the post, feel free to reach out to me anytime. I would be happy to discuss how to make your next ReactJS Project secure and safe.</p>
]]></content:encoded></item><item><title><![CDATA[How to Serve Static Files using NGINX in 3 Simple Steps? 💡]]></title><description><![CDATA[NGINX has been the most popular web server for many years now, and it is used by a large number of websites and businesses around the world. NGINX is a very powerful tool and can be used to accomplish a lot of different tasks. 
This blog will be abou...]]></description><link>https://blog.theinfosecguy.xyz/how-to-serve-static-files-using-nginx-in-3-simple-steps</link><guid isPermaLink="true">https://blog.theinfosecguy.xyz/how-to-serve-static-files-using-nginx-in-3-simple-steps</guid><category><![CDATA[THW Cloud Computing]]></category><category><![CDATA[nginx]]></category><category><![CDATA[Developer]]></category><category><![CDATA[Devops]]></category><category><![CDATA[AWS]]></category><dc:creator><![CDATA[Keshav Malik]]></dc:creator><pubDate>Mon, 09 May 2022 14:31:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1652101040257/wKNJ3Qfbd.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a target="_blank" href="https://www.nginx.com/">NGINX</a> has been the most popular web server for many years now, and it is used by a large number of websites and businesses around the world. NGINX is a very powerful tool and can be used to accomplish a lot of different tasks. </p>
<p>This blog will be about one of those various functions, and it will be about hosting static files on a server using NGINX.</p>
<h2 id="heading-step-1-editing-the-nginx-config-file">Step 1: Editing the NGINX Config File</h2>
<p>First of all, we'll have to edit the NGINX config file to add the directory, which will serve static content. Open the NGINX config file using the command:</p>
<pre><code><span class="hljs-attribute">sudo</span> vi /etc/nginx/nginx.conf   <span class="hljs-comment"># OR /etc/nginx/sites-enabled</span>
</code></pre><h2 id="heading-step-2-updating-the-location-block">Step 2: Updating the Location Block</h2>
<p>Once you have opened the file using the <code>vi</code> editor, create a new <code>location</code> block in the <code>server</code> block.</p>
<pre><code>server {
   server_name <span class="hljs-operator">&lt;</span><span class="hljs-operator">&gt;</span>;
   location <span class="hljs-operator">/</span> {
     ...
   }

   location <span class="hljs-operator">/</span>files<span class="hljs-operator">/</span> {
      root <span class="hljs-operator">/</span><span class="hljs-keyword">var</span><span class="hljs-operator">/</span>www;
   }
}
</code></pre><p>In the above code snippet, we have added a new location block for the <code>/files</code> path and updated the <code>root</code> directive to point at <code>/var/www</code>. Now let's create an empty directory named <code>/files</code> on the above location.</p>
<blockquote>
<p><strong>Note</strong>: As we use the <code>root</code> directive in the <code>location</code> block, NGINX will add the <code>route</code> name to all paths. For example, if you request any file, NGINX will look it in the <code>/var/www/files</code> directory.</p>
</blockquote>
<pre><code>cd <span class="hljs-operator">/</span><span class="hljs-keyword">var</span><span class="hljs-operator">/</span>www <span class="hljs-operator">&amp;</span><span class="hljs-operator">&amp;</span> mkdir files
</code></pre><p>Change the directory and create any file for testing purposes.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> files
sudo touch hello.txt  <span class="hljs-comment"># Add some random text too</span>
</code></pre>
<h2 id="heading-step-3-restart-the-nginx">Step 3: Restart the NGINX</h2>
<p>Restart the NGINX server using the following command:</p>
<pre><code class="lang-bash">sudo service nginx restart
</code></pre>
<p>Test the NGINX configuration using <code>sudo nginx -t</code> to make sure there are no errors in the file.</p>
<h2 id="heading-accessing-the-static-files">Accessing the Static Files 🚀</h2>
<p>To access the files, you can simply visit the server URL with the route that is mentioned in the location block (<code>/files</code>)</p>
<pre><code class="lang-bash">curl &lt;&lt;Server_URL&gt;&gt;/files/&lt;&lt;file_name&gt;&gt;
</code></pre>
<p>If you liked this post or found it interesting, give it a thumbs-up 👍</p>
<p>Thank you for reading! 💯</p>
]]></content:encoded></item><item><title><![CDATA[ServerGen: CRA Alternative for NodeJS]]></title><description><![CDATA[This weekend I had a chance to dive into my old side project ServerGen. ServerGen is a CRA alternative for NodeJS.
NodeJS is a great framework, and I keep using it for my projects. But I don't like installing the dependencies, writing the same code, ...]]></description><link>https://blog.theinfosecguy.xyz/servergen-cra-alternative-for-nodejs</link><guid isPermaLink="true">https://blog.theinfosecguy.xyz/servergen-cra-alternative-for-nodejs</guid><category><![CDATA[Node.js]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Keshav Malik]]></dc:creator><pubDate>Tue, 05 Apr 2022 14:40:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1649152231961/BPRs3Ppum.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This weekend I had a chance to dive into my old side project <a target="_blank" href="https://www.npmjs.com/package/servergen">ServerGen</a>. ServerGen is a CRA alternative for NodeJS.</p>
<p><a target="_blank" href="https://nodejs.org/">NodeJS</a> is a great framework, and I keep using it for my projects. But I don't like installing the dependencies, writing the same code, and making the MVC directory structure again &amp; again, which is why I created ServerGen, which helps you set up a NodeJS project within seconds.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649169038901/_4-Erfwb-.jpg" alt="Using ServerGen" /></p>
<h3 id="heading-what-is-currently-supported">What is Currently Supported?</h3>
<p>ServerGen currently supports the following features:</p>
<ul>
<li>MVC Directory Structure ( Along with .gitignore file )</li>
<li>Multiple View Engine ( Pug, EJS, HBS )</li>
<li>Docker Support </li>
<li>Express/Node Server Boilerplate</li>
<li>Mongoose Boilerplate for MongoDB</li>
</ul>
<h3 id="heading-whats-yet-to-come">What's Yet to Come?</h3>
<ul>
<li>Swagger Documentation</li>
<li>Passport Authentication</li>
<li>Sequalize ORM for MySQL &amp; PostgreSQL</li>
</ul>
<h3 id="heading-how-to-use-it">How to use it?</h3>
<p>To use ServerGen, make sure you have NodeJS installed on your system. Install ServerGen by using the command <code>npm i servergen</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649168284353/6mrHL27SH.png" alt="ServerGen (1).png" /></p>
<p>Liked the project? Do give it a ⭐ on GitHub!</p>
<p>Thank you for reading! 🚀</p>
]]></content:encoded></item><item><title><![CDATA[How to use Multiple SSH-Keys for Different Repositories on Server? ⚡⚡]]></title><description><![CDATA[Have you ever faced a situation where you need to use multiple SSH Keys for different repositories on a single server? If yes, then you are indeed not alone. Many developers face this situation, and this blog is for them. This blog will give you a co...]]></description><link>https://blog.theinfosecguy.xyz/how-to-use-multiple-ssh-keys-for-different-repositories-on-server</link><guid isPermaLink="true">https://blog.theinfosecguy.xyz/how-to-use-multiple-ssh-keys-for-different-repositories-on-server</guid><category><![CDATA[Web Development]]></category><category><![CDATA[server]]></category><category><![CDATA[ssh]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[Keshav Malik]]></dc:creator><pubDate>Sun, 27 Mar 2022 06:11:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1648357570721/OExtS0e9D.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Have you ever faced a situation where you need to use multiple SSH Keys for different repositories on a single server? If yes, then you are indeed not alone. Many developers face this situation, and this blog is for them. This blog will give you a complete understanding of how multiple SSH-Key can be helpful for you and how you can use those.</p>
<h2 id="heading-why-do-you-need-ssh-keys">Why Do You Need SSH Keys?</h2>
<p>With the help of SSH keys, a developer can connect to a remote server using a secure network connection. SSH-keys also permits the developer to access their remote repositories without being asked to enter user names or passwords every time.</p>
<h2 id="heading-step-1-generating-ssh-keys">Step 1: Generating SSH Keys</h2>
<p>You can quickly generate SSH Keys on your server using ssh-keygen by using the following command.</p>
<p><code>ssh-keygen -t rsa -c "first key"</code></p>
<p>After using this command, you'll be prompted to enter the output file location and the name. SSH keys are usually stored in the <code>.ssh</code> directory. Feel free to use any location and name of your choice. </p>
<p>Let's use this dummy location for example: <code>~/.ssh/key1</code></p>
<p>Here <code>key1</code> is the name for SSH keys. Once done, two files (Private and Public Key) will be saved in the output directory.</p>
<p>Use the same steps to generate one more SSH Key and name it <code>key2</code></p>
<h2 id="heading-step-2-adding-ssh-keys-to-github-repositories">Step 2: Adding SSH Keys to GitHub Repositories</h2>
<p>After setting up SSH Keys, add the Public Key to the GitHub Repository. To add the SSH key in the GitHub Repo, Navigate to Repository &lt; Setting &lt; Deploy Keys.</p>
<p>Add both the keys to two different repositories (Public or Private).</p>
<h2 id="heading-step-3-setting-up-ssh-config">Step 3: Setting up SSH Config</h2>
<p>Now it's time to add SSH Keys in the SSH Config File on the server. This allows SSH to identify which key to use for the host.</p>
<p>Let's use the <code>vi</code> editor to edit the SSH Config (<code>~/.ssh/config</code>)  file. Open the file using <code>vi ~/.ssh/config</code> and paste the following in the file.</p>
<pre><code>Host <span class="hljs-keyword">private</span><span class="hljs-operator">-</span>repo<span class="hljs-number">-1</span>
HostName github.com
User git
IdentityFile <span class="hljs-operator">~</span><span class="hljs-operator">/</span>.ssh/key1

Host <span class="hljs-keyword">private</span><span class="hljs-operator">-</span>repo<span class="hljs-number">-2</span>
HostName github.com
User git
IdentityFile <span class="hljs-operator">~</span><span class="hljs-operator">/</span>.ssh/key2
</code></pre><p>Here <code>Host</code> represents the Repository's name, and <code>IdentityFile</code> means the file's location.</p>
<h2 id="heading-step-4-clone-the-repository">Step 4: Clone the Repository</h2>
<p>That's all you need to do. Now to clone the repo, use the following command.</p>
<p><code>git clone &lt;Host&gt;:&lt;Username-Org_Name&gt;/&lt;Repository_Name&gt;</code></p>
<p>For example, I have a private repository with the name <code>hashnode</code>, and in the SSH config file (Step 3), I've set Host to <code>hashnode</code>, so the command will be:</p>
<p><code>git clone hashnode:myusername/hashnode</code></p>
<p>And that's just it!</p>
<p>I hope you found a solution to the problem you were looking for. If you have any queries regarding this topic, then please comment below. We will be happy to help you.</p>
]]></content:encoded></item></channel></rss>