<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Andrew M</title>
    <description>The latest articles on DEV Community by Andrew M (@mayormaier).</description>
    <link>https://dev.to/mayormaier</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F459325%2Fa9c6836f-a842-4f51-b734-e6939b273c1f.png</url>
      <title>DEV Community: Andrew M</title>
      <link>https://dev.to/mayormaier</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mayormaier"/>
    <language>en</language>
    <item>
      <title>Deploy Keycloak Clients and Roles with Code</title>
      <dc:creator>Andrew M</dc:creator>
      <pubDate>Fri, 09 Dec 2022 23:27:27 +0000</pubDate>
      <link>https://dev.to/mayormaier/deploy-keycloak-clients-and-roles-with-code-395l</link>
      <guid>https://dev.to/mayormaier/deploy-keycloak-clients-and-roles-with-code-395l</guid>
      <description>&lt;p&gt;We last discussed how to structure our Keycloak role organization within a microservice deployment context. This discussion provides the foundation for what we will discuss today: leveraging &lt;a href="https://www.redhat.com/en/topics/automation/what-is-infrastructure-as-code-iac" rel="noopener noreferrer"&gt;Infrastructure as Code (IAC)&lt;/a&gt; to deploy Keycloak clients and roles easily. The goal for this project is to easily add additional microservice integrations to Keycloak so that they can be set up with minimal configuration. The tool will come as a lightweight CLI that interacts with a Keycloak server deployment to perform the client and role creation. THe tool will also provide smart defaults so new users can take advantage of this service without a full understanding of each setting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Proposed IaC Schema
&lt;/h2&gt;

&lt;p&gt;Here is a &lt;a href="https://github.com/elmsln/kraxen/blob/main/keycloak-deploy.schema.json" rel="noopener noreferrer"&gt;link to the JSON schema&lt;/a&gt;&lt;br&gt;
Here is a &lt;a href="https://github.com/mayormaier/keycloak-microservice-docs/blob/main/resources/keycloak-schema-docs.md" rel="noopener noreferrer"&gt;link to the schema documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The proposed schema for this tool breaks down the Keycloak client configuration into more manageable and modular segments to ease template creation. For example, in this simple example, the hierarchical nature of the template enables users to specify their client features more easily.&lt;/p&gt;
&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;In order to run the kraxen CLI, you must have NPM installed.&lt;br&gt;
Install the CLI tool, aka Kraxen, by cloning the kraxen repository and installing it globally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/elmsln/kraxen &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;kraxen
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Firstly, a configuration file for kraxen (&lt;code&gt;.kraxen&lt;/code&gt;) must be created in either a user's home directory, or the current working directory. The configuration file must specify three things: &lt;code&gt;KEYCLOAK_HOST&lt;/code&gt;, &lt;code&gt;KEYCLOAK_ADMIN_USERNAME&lt;/code&gt;, and &lt;code&gt;KEYCLOAK_ADMIN_PASSWORD&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;KEYCLOAK_HOST=https://keycloak-host.org
KEYCLOAK_ADMIN_USERNAME=user
KEYCLOAK_ADMIN_PASSWORD=password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These values can also be set via environment variables.&lt;/p&gt;

&lt;p&gt;Next, the configuration file for the client must be created. These configuration files are YAML files that define attributes of a Keycloak client that kraxen will create. Kraxen is configured to set smart defaults for a decoupled application that implements OIDC authentication. The only required values are the &lt;code&gt;clientId&lt;/code&gt;, &lt;code&gt;protocol&lt;/code&gt;, &lt;code&gt;realm&lt;/code&gt; settings. Most of the other settings are set as smart defaults and can be overridden via the YAML configuration file. &lt;a href="https://github.com/elmsln/kraxen/blob/main/testclient_kc.yaml" rel="noopener noreferrer"&gt;See an example of a template here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lastly, we can run the kraxen CLI and watch our template create!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kraxen -t template-file.yaml -c kraxen-config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-c&lt;/code&gt; flag can be omitted if the &lt;code&gt;.kraxen&lt;/code&gt; configuration is present in the user's home directory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Notes
&lt;/h2&gt;

&lt;p&gt;This initial executable is just a simple proof-of-concept model to demonstrate how Keycloak APIs can be leveraged to programmatically create clients and roles for use within an application. In the future, the CLI will scaffold out the template based on prompts that a user enters. It will also include sub-commands such as &lt;code&gt;kraxen init&lt;/code&gt; to begin CLI setup, &lt;code&gt;kraxen create&lt;/code&gt; to create a new set of Keycloak clients and roles, and &lt;code&gt;kraxen sync&lt;/code&gt; to update the client configuration to match the current template. I hope to use the great example of elmsln's wcfactory tool to build a more robust CLI that can integrate even more features.&lt;/p&gt;

&lt;p&gt;Lastly, I would like to shout out coveooss and their &lt;a href="https://github.com/coveooss/json-schema-for-humans" rel="noopener noreferrer"&gt;JSON Schema For Humans tool&lt;/a&gt;, which allowed me to produce markdown documentation for the Infrastructure as Code schema that I defined above. Kudos!&lt;/p&gt;

</description>
      <category>security</category>
      <category>microservices</category>
      <category>keycloak</category>
    </item>
    <item>
      <title>Integrating Keycloak Identity Management in the Frontend and Backend</title>
      <dc:creator>Andrew M</dc:creator>
      <pubDate>Fri, 09 Dec 2022 22:52:33 +0000</pubDate>
      <link>https://dev.to/mayormaier/integrating-keycloak-identity-management-in-the-frontend-and-backend-c8o</link>
      <guid>https://dev.to/mayormaier/integrating-keycloak-identity-management-in-the-frontend-and-backend-c8o</guid>
      <description>&lt;p&gt;Now that our authentication system is in place, client is created, and frontend assets are in motion, we will explore how authentication can be implemented into a micro-frontend component. The intended use case would be that this micro frontend could operate alone, or inside of a larger content system with other components that require authentication.&lt;/p&gt;

&lt;p&gt;For the purposes of this example, let's consider a "discussion" microservice with a frontend web component and backend API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frontend Component
&lt;/h2&gt;

&lt;p&gt;For the micro-frontend use case and other decoupled applications (i.e., applications with a distinctly separate frontend and backend service that communicate via API calls), a "public" Keycloak client is required. Public clients are used with applications that expose the frontend logic of an application and make it impossible to store Keycloak secrets securely. The alternative, a "confidential" client utilizes a secret key to create a trust relationship between the application and the Keycloak server. These types of clients are applicable for monolithic or server-rendered applications. Public clients enable applications to conduct authentication flows with Keycloak to return a signed token that contains information about the user. Security controls are implemented via origin policies and well defined redirect URIs. By controlling the endpoints that Keycloak is able to redirect users to, we are able to prevent external or rogue services from hijacking our Keycloak client and receiving tokens on behalf of our users.&lt;/p&gt;

&lt;p&gt;In order for the frontend component to execute the authentication flow, there must be support within the front end of the application to prompt the user to log in before application content can be displayed. This portion of the front end should be modular, so that it follows a singleton pattern on a page. For example, if the discussion component was placed on a page by itself, the component should prompt the user to log in. However, if the discussion component was placed in the context of a larger application that requires authentication, the individual components within that application should defer to the wider application context without handling authentication individually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authentication Flow
&lt;/h2&gt;

&lt;p&gt;Based on the requirement outlined above, the Open ID Connect (OIDC) &lt;a href="https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow" rel="noopener noreferrer"&gt;Authorization Code Flow&lt;/a&gt; should be implemented. This flow is implemented by the &lt;a href="https://www.keycloak.org/docs/latest/securing_apps/index.html#_javascript_implicit_flow" rel="noopener noreferrer"&gt;keycloak-js frontend adapter by default.&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First, the user will visit the page containing the web component. &lt;em&gt;At this point, the micro-frontend is "disabled". A login button will be displayed to prompt the user to log in to the application.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;When the user clicks on the login button, a second window will appear, directing the user to the Keycloak sign-in page. With this request, the application includes a redirect URL that defines where the user will be redirected after the authentication process.&lt;/li&gt;
&lt;li&gt;The user selects an identity provider and is redirected to their log-in page.&lt;/li&gt;
&lt;li&gt;The user authenticates with their identity provider of choice. Upon a successful authentication, the user is redirected from the identity provider back to Keycloak.&lt;/li&gt;
&lt;li&gt;The user is then redirected from Keycloak back to the application using the redirect URI specified during the original authentication request. The response includes an "authorization code" that is used to obtain the Access, Identity, and Refresh tokens from Keycloak.&lt;/li&gt;
&lt;li&gt;The application requests the Access, Identity, and Refresh tokens from Keycloak.&lt;/li&gt;
&lt;li&gt;Keycloak validates that the requesting application is able to request the tokens.&lt;/li&gt;
&lt;li&gt;Keycloak returns the tokens to the application. &lt;em&gt;At this point, the application is "enabled" and can make API requests to resources that require authentication.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;The application makes requests that load the initial data from the API. The Identity token is included in this API call.&lt;/li&gt;
&lt;li&gt;The API verifies that the token is valid and that the user has the appropriate permissions to execute the request. The application then issues a response to the application.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A benefit to using the keycloak-js library is the abstraction of the token exchanges from steps 5-8 in the flow above. The keycloak-js adapter also builds the requests and URLs that are requires to begin the authentication flow. This enables developers to simply focus on the visual and system requirements for their application without focusing on the cumbersome request flow and security requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Backend Implementation
&lt;/h2&gt;

&lt;p&gt;A few functions must be defined on the backend API in order to enable it to participate in the flow defined above. Firstly, it should verify the validity of the token provided by the user. The Open ID Connect specification defines that JSON Web Tokens (JWTs) will be provided as the Identity, Access, and Refresh tokens in this case, thus developers can use this specification to validate user requests without interfacing directly with the keycloak server.&lt;/p&gt;

&lt;p&gt;Firstly, the backend API should check if the identity token is valid. A valid token is one that is signed properly and is not expired. The &lt;a href="https://www.npmjs.com/package/jsonwebtoken" rel="noopener noreferrer"&gt;jsonwebtoken package&lt;/a&gt; contains functions that can be called to verify that a token is valid. In order to execute the &lt;code&gt;jwt.verify&lt;/code&gt; function, the public key for the Keycloak realm should be defined. This public key is required to verify the token signature.&lt;/p&gt;

&lt;p&gt;In cases where keycloak roles are utilized, the role claim within the token should be evaluated against the list of applicable roles for the given API. Since the token has been declared cryptographically valid at this point, the role claim can be trusted and evaluated independent of the Keycloak server. This requires the API to be aware of the applicable keycloak roles for each resource thus centralizing the authorization decision. A benefit of this is that other identity management tools with role definition capabilities can be used in place of keycloak as a systems needs change. This reduces the amount of time required to process each API request.&lt;/p&gt;

&lt;p&gt;In cases where processing related to the requesting user is required, the API should verify that the user record exists and create it if it does not. Keycloak returns the &lt;code&gt;sub&lt;/code&gt; claim as a unique identifier for the user, &lt;a href="https://auth0.com/docs/get-started/apis/scopes/openid-connect-scopes#standard-claims" rel="noopener noreferrer"&gt;following the OIDC specification.&lt;/a&gt; An example of this requirement for the discussion application would be if a list of users is maintained with a unique id. Tracking the user's ID would allow them to edit or delete their posts without granting the user admin permissions.&lt;/p&gt;

</description>
      <category>security</category>
      <category>microservices</category>
      <category>keycloak</category>
    </item>
    <item>
      <title>Considerations for Creating Keycloak Roles</title>
      <dc:creator>Andrew M</dc:creator>
      <pubDate>Mon, 10 Oct 2022 22:11:33 +0000</pubDate>
      <link>https://dev.to/mayormaier/considerations-for-creating-keycloak-roles-5290</link>
      <guid>https://dev.to/mayormaier/considerations-for-creating-keycloak-roles-5290</guid>
      <description>&lt;p&gt;Now that we have Keycloak up and running, we are ready to start configuring it for our microservices. A large part of keycloak is the concept of &lt;em&gt;roles&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What are roles exactly? Keycloak defines roles as the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Roles are type or category of user. Applications often assign access and permissions to specific roles rather than individual users as dealing with users can be too fine grained and hard to manage.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"A user role mapping defines a mapping between a role and a user. A user can be associated with zero or more roles. This role mapping information can be encapsulated into tokens and assertions so that applications can decide access permissions on various resources they manage."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One important thing to get started with Keycloak is to understand that it does &lt;strong&gt;NOT&lt;/strong&gt; link roles to &lt;em&gt;application specific&lt;/em&gt; permissions. Instead, permissions must be assigned within the application (or microservice). With that being said, we should consider how to organize groups of users based on the level of permissions that they require, and also decide any global roles that have implications across all applications (e.g., Admin, default role, etc.)&lt;/p&gt;

&lt;p&gt;There are some additional constructs that Keycloak provides to make role management easier. For example:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Groups&lt;/strong&gt; manage groups of users. Attributes can be defined for a group. &lt;em&gt;You can map roles to a group&lt;/em&gt; as well. Users that become members of a group inherit the attributes and role mappings that group defines.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;composite role&lt;/strong&gt; is a role that can be associated with other roles. For example a &lt;code&gt;superuser&lt;/code&gt; composite role could be associated with the &lt;code&gt;sales-admin&lt;/code&gt; and &lt;code&gt;order-entry-admin&lt;/code&gt; roles. If a user is mapped to the &lt;code&gt;superuser&lt;/code&gt; role they also inherit the &lt;code&gt;sales-admin&lt;/code&gt; and &lt;code&gt;order-entry-admin&lt;/code&gt; roles.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Client scopes&lt;/strong&gt; define protocol mappers (configuration to pass specific user attributes) and role scope mappings for that client. &lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;client roles&lt;/strong&gt;, clients can define roles that are specific to them. This is basically a role namespace dedicated to the client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Proposed Role Structure
&lt;/h2&gt;

&lt;p&gt;Typically, Keycloak role structures mimic organizational structure, where each role is related to a specific job title. This makes sense in cases which job titles and roles do not change frequently. In our case, we must consider the educational environment, where there are 3-5 job titles: Administrator, Professor, Student, etc. Clearly, we need to have more granular control.&lt;/p&gt;

&lt;h3&gt;
  
  
  Global Roles
&lt;/h3&gt;

&lt;p&gt;Global Roles apply to all applications within the realm. These are more applicable to Administrative permissions and developers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Examples:&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Site Admin:&lt;/strong&gt; global.admin (i.e., access to global application configuration)&lt;br&gt;
&lt;strong&gt;Site Developer:&lt;/strong&gt; global.dev (i.e., access to test and development resources)&lt;/p&gt;

&lt;p&gt;Additionally, there should be global roles for authenticated users to differentiate them from unauthenticated users, even if the user does not match the required roles to perform a specific action.&lt;/p&gt;

&lt;h3&gt;
  
  
  Application Specific Roles
&lt;/h3&gt;

&lt;p&gt;Application Specific Roles broadly limit the types of actions that users may take in a specific application. For example, these roles could be used to grant user access to create new content within the application or adjust global settings. General Application Specific Roles are not granular and are not meant to control access to content.&lt;/p&gt;

&lt;p&gt;Additionally, Keycloak client roles define smaller sets of roles to pass to each client. Role scopes will ensure that permission grants are efficient and roles which are not required are not passed to the client.&lt;/p&gt;

&lt;p&gt;Examples:&lt;br&gt;
Application User: .user (i.e., create new application resources and manage their own)&lt;br&gt;
Application Admin: .admin (i.e., access to application specific configuration)&lt;/p&gt;

&lt;h3&gt;
  
  
  Site Specific Roles
&lt;/h3&gt;

&lt;p&gt;Application Specific roles are a subset of Application Specific Roles. They grant user access to individual sites within an application, and make it possible to provide different permissions for different microservices. For example, A user could have read access to site content, but write access to create comments on that site.&lt;/p&gt;

&lt;p&gt;Examples:&lt;br&gt;
Site Admin: ..admin (i.e., manage site settings and content)&lt;br&gt;
Service User: ..user (i.e., view/edit/update created service content)&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Deal With Roles
&lt;/h2&gt;

&lt;p&gt;Now that we have a role structure outlined, we must consider the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How roles should be created&lt;/li&gt;
&lt;li&gt;How roles should be assigned to users&lt;/li&gt;
&lt;li&gt;How permissions should delegated to users&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Questions 1 and 2 will be answered in later parts of the series, as we plan to automate role creation and assignment. The Keycloak REST API makes it easy for administrators to automate the creation roles as new applications are registered. Additionally, the creation of Keycloak clients (or application registrations within Keycloak) should be automated within the deployment lifecycle.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.keycloak.org/docs/latest/server_admin/" rel="noopener noreferrer"&gt;Keycloak Server Administration Guide&lt;/a&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>microservices</category>
      <category>keycloak</category>
    </item>
    <item>
      <title>Installing Nessus Agents on AWS EC2</title>
      <dc:creator>Andrew M</dc:creator>
      <pubDate>Mon, 03 Oct 2022 18:07:34 +0000</pubDate>
      <link>https://dev.to/mayormaier/installing-nessus-agents-on-aws-ec2-4eda</link>
      <guid>https://dev.to/mayormaier/installing-nessus-agents-on-aws-ec2-4eda</guid>
      <description>&lt;p&gt;Public cloud services like AWS make it easy to create scalable resources that expand and contract with load. While this solves many operational IT problems, it fails to address them securely.&lt;/p&gt;

&lt;p&gt;The threat landscape is constantly evolving, so IT teams must be ahead of the curve when it comes to patching. &lt;a href="https://www.tenable.com/products/nessus" rel="noopener noreferrer"&gt;Nessus&lt;/a&gt; is one vulnerability scanning and remediation tool that many organizations utilize to monitor the security of their assets. Nessus is deployed via an agent that runs on each asset. It runs automated vulnerability scans and reports the results to a centralized cloud platform which can be accessed by security analysts.&lt;/p&gt;

&lt;p&gt;Nessus is a great solution for security on premises- but it also can protect cloud resources. As part of my centralized microservice strategy, I implemented Keycloak Authentication as a cloud instance. To comply with organizational policy, all servers utilizing the company's domain name must have the Nessus agent installed. This posed a challenge as I originally planned to deploy Keycloak with &lt;a href="https://docs.aws.amazon.com/AmazonECS/latest/userguide/what-is-fargate.html" rel="noopener noreferrer"&gt;ECS Fargate&lt;/a&gt; - a serverless container solution. ECS also works with EC2 to expose the underlying infrastructure and enable administrators to have greater control over the host.&lt;/p&gt;

&lt;p&gt;As with many of my deployments, I leveraged AWS CloudFormation to deploy my resources. This enables me to leverage Infrastructure as Code to maintain visibility and consistency into my infrastructure configurations. See my &lt;a href="https://github.com/mayormaier/keycloak-microservice-docs/blob/main/resources/keycloak-auth-ec2.yaml" rel="noopener noreferrer"&gt;CloudFormation template for this deployment here.&lt;/a&gt; &lt;strong&gt;NOTE:&lt;/strong&gt; You may experience some problems with this CloudFormation template if you do not complete the below configuration steps. Please read below before deploying the template.&lt;/p&gt;

&lt;p&gt;ECS on EC2 requires a few additional resources to operate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Auto Scaling Group:&lt;/strong&gt; Defines a set of EC2 instances that can dynamically grow and shrink with application demand. ECS will schedule containers to run on these instances.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EC2 Launch Configuration:&lt;/strong&gt; Defines the configuration of EC2 instances that will be launched into the autoscaling group. Some configuration options include: AMI ID, Security Groups, and Instance Type. Another configuration item is EC2 User Data, which is a bootstrap script that is run when the instance is launched.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In our use case, user data is the primary mechanism for configuring the Nessus agent on our instances. Because User Data is defined in the launch configuration, we can be sure that each instance launched in our ECS Auto Scaling Group will include the Nessus Agent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration Steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Download the Nessus Agent Installer:&lt;/strong&gt; Nessus packages are available for download directly from the nessus website. In fact, Nessus requires users to download it right from their website. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create an Amazon S3 Bucket to store the Nessus installers:&lt;/strong&gt; Next, create an S3 bucket to store the Nessus agent installer. This bucket should block all public access. Upload the installer to this bucket and note the filename.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create a Role that enables EC2 instance to access files from the S3 bucket:&lt;/strong&gt; Create a role that allows &lt;code&gt;s3:GetObject&lt;/code&gt; access to the agent storage s3 bucket. Note: If using the provided CloudFormation template, the role and instance profile are configured, &lt;strong&gt;BUT&lt;/strong&gt; they reference a &lt;a href="https://gist.github.com/mayormaier/86d05d74f0c38dcf314a0aeab7c91a84" rel="noopener noreferrer"&gt;User managed policy&lt;/a&gt; called &lt;code&gt;S3NessusAgentAccess&lt;/code&gt;. This policy should be created before deploying the template. You should be sure to replace the bucket name &lt;code&gt;nessus-agents&lt;/code&gt; in the policy to reflect your bucket name.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use the following UserData to install the agent:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
yum &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; aws-cfn-bootstrap
yum &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; unzip
&lt;span class="nb"&gt;echo &lt;/span&gt;&lt;span class="nv"&gt;ECS_CLUSTER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ECSCluster&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /etc/ecs/ecs.config
curl &lt;span class="s2"&gt;"https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"awscliv2.zip"&lt;/span&gt;
unzip awscliv2.zip
&lt;span class="nb"&gt;sudo&lt;/span&gt; ./aws/install 
/usr/local/bin/aws s3 &lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NessusAgentUri&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
rpm &lt;span class="nt"&gt;-ivh&lt;/span&gt; NessusAgent-&lt;span class="k"&gt;*&lt;/span&gt;.rpm
/opt/nessus_agent/sbin/nessuscli agent &lt;span class="nb"&gt;link&lt;/span&gt; &lt;span class="nt"&gt;--key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NessusAgentKey&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--groups&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NessusAgentGrp&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--cloud&lt;/span&gt;
service nessusagent stop
/opt/nessus_agent/sbin/nessusd &lt;span class="nt"&gt;-R&lt;/span&gt;
service nessusagent start
/opt/aws/bin/cfn-signal &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;--stack&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;AWS&lt;/span&gt;::StackName&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--resource&lt;/span&gt; ECSAutoScalingGroup &lt;span class="nt"&gt;--region&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;AWS&lt;/span&gt;::Region&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This user data is formatted for CloudFormation with a few required parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;NessusAgentUri:&lt;/strong&gt; The path of the Nessus agent installer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NessusAgentKey:&lt;/strong&gt; The tenant key for Nessus&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NessusAgentGrp:&lt;/strong&gt; The name of the group to link the agent to&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ECSCluster:&lt;/strong&gt; [Optional] The name of the ECS Cluster that the instance should be available to.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another note for this UserData is that it is designed to work within ECS configured via CloudFormation. This script would also work with regular EC2 instances after brief modifications.&lt;/p&gt;

&lt;p&gt;If not using this script with AWS ECS, omit the following line:&lt;br&gt;
&lt;code&gt;echo ECS_CLUSTER=${ECSCluster} &amp;gt;&amp;gt; /etc/ecs/ecs.config&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If not using this script with AWS CloudFormation, replace all CloudFormation parameters, and omit the following lines:&lt;br&gt;
&lt;code&gt;yum install -y aws-cfn-bootstrap&lt;/code&gt;&lt;br&gt;
&lt;code&gt;/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ECSAutoScalingGroup --region ${AWS::Region}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Lastly, if you are using this script with an AMI that includes the AWS CLI (e.g., Amazon Linux 2), omit the installaiton of the CLI package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yum &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; unzip
curl &lt;span class="s2"&gt;"https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"awscliv2.zip"&lt;/span&gt;
unzip awscliv2.zip
&lt;span class="nb"&gt;sudo&lt;/span&gt; ./aws/install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>security</category>
      <category>aws</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Architecting a Keycloak Deployment in AWS</title>
      <dc:creator>Andrew M</dc:creator>
      <pubDate>Thu, 22 Sep 2022 22:31:03 +0000</pubDate>
      <link>https://dev.to/mayormaier/architecting-a-keycloak-deployment-in-aws-2id4</link>
      <guid>https://dev.to/mayormaier/architecting-a-keycloak-deployment-in-aws-2id4</guid>
      <description>&lt;p&gt;Now that we've defined our use case for Keycloak, let's dive in to how we will actually deploy it. Keycloak is designed to support a variety of environments including Docker, Kubernetes, and OpenShift. For our use case, we will be utilizing Amazon Web Services Elastic Container Service (ECS). ECS is a contianer orchestration playform that enables users to deploy their continers to the cloud with minimal overhead. If you've been &lt;em&gt;baffled&lt;/em&gt; by Kubernetes, I assure you that ECS will be a much better experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;

&lt;p&gt;First, let's take a look at the various services at play in this deployment:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_FHQNxjz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/mayormaier/keycloak-microservice-docs/main/assets/images/KeycloakDeployment.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_FHQNxjz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/mayormaier/keycloak-microservice-docs/main/assets/images/KeycloakDeployment.jpeg" alt="Architecture Diagram" width="800" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=""&gt;Take a look at the CloudFormation Template for this deployment here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  VPC Overview
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Virtual Private Clouds (VPCs)&lt;/strong&gt; are logically isolated sections of the AWS cloud that act are assigned to one customer. Think of a VPC like a virtual data center in the cloud. Each VPC is divided into &lt;strong&gt;subnets&lt;/strong&gt;, each with their own &lt;strong&gt;route table&lt;/strong&gt; and set of &lt;strong&gt;security groups&lt;/strong&gt;. Subnets are blocks of IP address space within the larger VPC block. Route tables determine how each subnet handles traffic, and security groups act as a host based firewall, but security groups can be applied to multiple hosts. For more information about the structure of VPCs, check out &lt;a href="https://www.bmc.com/blogs/aws-vpc-virtual-private-cloud/" rel="noopener noreferrer"&gt;this article by BMC's Joe Hertvik&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How is Traffic Routed?
&lt;/h3&gt;

&lt;p&gt;Firstly, traffic destined for the Keycloak server will be sent to the resolved DNS CNAME that points to the &lt;strong&gt;Application Load Balancer.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next, after entering the Amazon Web Services network, the traffic traverses to the &lt;strong&gt;Internet Gateway&lt;/strong&gt; Internet Gateways are common constructs of the VPC, and they are required to route traffic from the internet to VPC based hosts and services.&lt;/p&gt;

&lt;p&gt;After entering the VPC, requests are routed to the first public subnet where the &lt;strong&gt;Application Load Balancer&lt;/strong&gt; is located. Elastic Load Balancers (the umbrella term for all load balancers) distribute traffic across a group of hosts to maintain high availability and scalability. Application Load balancers enable specific route based forwarding through a set of rules. In our use case, we have a single rule that simply forwards traffic to the Keycloak instance.&lt;/p&gt;

&lt;p&gt;Additionally, the &lt;strong&gt;Application Load Balancer&lt;/strong&gt; performs TLS termination for our Keyloak deployment, and enables users to connect securely to the Keycloak server. A TLS Certificate is defined in &lt;strong&gt;Amazon Certificate Manager&lt;/strong&gt;, which is referenced by the Application Load Balancer. As requests arrive at the load balancer, the certificate is returned to begin the TLS encryption process.&lt;/p&gt;

&lt;p&gt;Next, traffic is routed into the private subnet where our application resources live. We opted to utilize &lt;strong&gt;ECS on EC2&lt;/strong&gt; for this deployment, as it affords us the additional control required to meet compliance requirements. In this deployment strategy, containers are scheduled to run on a defined EC2 instance that is managed by the user. Even though this responsibility is on the user, container configuration and management is still defined by the ECS service. One requirement of Application Load Balancers is the definition of multiple subnets across multiple availability zones to schedule containers in. In the event that a container exits or fails a health check, ECS will deploy an instance in another availability zone, and start the container there. Thus, high availability is built into the deployment by default.&lt;/p&gt;

&lt;p&gt;Lastly, the deployment reaches the Keycloak container, running the latest &lt;a href="https://quay.io/repository/keycloak/keycloak" rel="noopener noreferrer"&gt;Keycloak Docker image&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;ECS deployments are broken into &lt;strong&gt;Clusters&lt;/strong&gt;, which can have many &lt;strong&gt;services&lt;/strong&gt; that contain a set of &lt;strong&gt;tasks&lt;/strong&gt;. Clusters typically contain all of the services required for a given application. For example, an application with multiple backend services would be grouped into the same cluster. A &lt;strong&gt;Task Definition&lt;/strong&gt; is a document that outlines the configuration for an ECS Task. Tasks are essentially containers that are running instances of the task definition. Task definitions can define a variety of configuration items such as the container image URI, environment variables, port mappings, and desired container counts.&lt;/p&gt;

&lt;p&gt;Because Keycloak requires a database to function, we've created an EC2 instance to run the database instance. We've chosen MariaDB, but many other options are available &lt;a href="https://www.keycloak.org/server/db" rel="noopener noreferrer"&gt;per the Keycloak documentation&lt;/a&gt;. In the future we may upgrade this to a true RDS instance, but for now, EC2 suits our needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuration Overview
&lt;/h3&gt;

&lt;p&gt;Much of the configuration for this deployment occurs within the Keycloak container's environment variables. In the event that the container needs to be restarted, all of the configuration can be referenced via the container's task definition.&lt;/p&gt;

</description>
      <category>security</category>
      <category>aws</category>
      <category>keycloak</category>
    </item>
    <item>
      <title>Introduction to User Authentication for Microservices</title>
      <dc:creator>Andrew M</dc:creator>
      <pubDate>Fri, 09 Sep 2022 00:48:12 +0000</pubDate>
      <link>https://dev.to/mayormaier/introduction-to-user-authentication-for-microservices-46em</link>
      <guid>https://dev.to/mayormaier/introduction-to-user-authentication-for-microservices-46em</guid>
      <description>&lt;p&gt;Do you have a collection of microservices that you've been painstakingly integrating into an authentication service one by one? Maybe you're running these services in a federated user environment, or you need a way to control authentication from a single point. Regardless of your situation, it is important to consider how to design an authentication system that is robust, extensible, and meets business requirements.&lt;/p&gt;

&lt;p&gt;Today, we'll be looking at a few standards to integrate authentication into microservices through a centralized identity and access management system. We'll be reviewing &lt;a href="https://www.okta.com/blog/2020/09/what-is-saml/" rel="noopener noreferrer"&gt;Security Assertion Markup Language&lt;/a&gt; (SAML) &lt;a href="https://www.okta.com/openid-connect/" rel="noopener noreferrer"&gt;OpenIDConnect&lt;/a&gt;, and &lt;a href="https://developer.okta.com/blog/2017/06/21/what-the-heck-is-oauth" rel="noopener noreferrer"&gt;Oauth2&lt;/a&gt;. We'll also begin to discuss how to integrate these services into applications at a high level. This article will begin a series that journeys through the process of integrating authentication at the system, backend, and frontend level. Our application model will follow &lt;a href="https://dev.to/btopro/building-micro-frontends-with-vercel-lit-45oe"&gt;btopro's microservice design process&lt;/a&gt;, with the goal of adding authentication to the &lt;a href="https://github.com/mayormaier/threaded-discussion" rel="noopener noreferrer"&gt;threaded-discussion web component&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Without further ado, lets get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Authentication standards
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Key Terms
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Authentication:&lt;/strong&gt; The process of confirming a user's identity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authorization:&lt;/strong&gt; The use of authentication data to grant access based on a given user's permissions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  SAML
&lt;/h3&gt;

&lt;p&gt;SAML is a standard that passes credentials from Identity Providers (IdP) to Service Providers (SP) aka applications (&lt;a href="https://www.okta.com/blog/2020/09/what-is-saml/" rel="noopener noreferrer"&gt;https://www.okta.com/blog/2020/09/what-is-saml/&lt;/a&gt;). IdPs &lt;em&gt;Authenticate&lt;/em&gt; users (e.g., Microsoft Active Directory) and SPs &lt;em&gt;authorize&lt;/em&gt; users.&lt;/p&gt;

&lt;p&gt;SAML passes informaiton between providers (and the user browser) via &lt;em&gt;SAML Assertions&lt;/em&gt;. Assertions are simply XML Documents that provide informaiton about a user.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Authentication assertions&lt;/strong&gt; prove a user’s identity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attribution assertions&lt;/strong&gt; pass SAML attributes—the pieces of data that provide information about the user—to the service provider.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authorization assertions&lt;/strong&gt; confirm whether the user is authorized to use a service—and what degree of authorization they have&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  OAuth2
&lt;/h3&gt;

&lt;p&gt;OAuth2 is a standard for "secure delegated access", or Authorization between applications. It provides claims for a smaller service (e.g., mycoolapp.com) to access data on another service, (e.g., Facebook). OAuth makes use of tokens (usually JWTs) to delegate access to applications for a set of resources.&lt;/p&gt;

&lt;p&gt;An important thing to remember is:&lt;br&gt;
    &amp;gt;"OAuth is NOT about authenticating the user, and this is key. OAuth 2.0 alone says absolutely nothing about the user. You just &amp;gt;have a token to get access to a resource." &lt;em&gt;Matt Raible, What the heck is OAuth2?&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  OpenIDConnect
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fmayormaier%2Fkeycloak-microservice-docs%2Fmain%2Fassets%2Fimages%2Fflow-channels-5d8996b3706cab1e4ac8f9ed716d6529d3970f91cbc3cb5ff5a21a94389d0e1d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fmayormaier%2Fkeycloak-microservice-docs%2Fmain%2Fassets%2Fimages%2Fflow-channels-5d8996b3706cab1e4ac8f9ed716d6529d3970f91cbc3cb5ff5a21a94389d0e1d.png" alt="OIDC Flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Building on top of the OAuth2 Framework, OpenIDConnect (OIDC) provides authentication via an &lt;em&gt;ID Token&lt;/em&gt;. This enables systems to share authentication state and user profile information in a predictable format. Without OpenIDConnect, developers are left to find an arbitrary authentication framework to combine with OAuth, which is complex and challenging.&lt;/p&gt;

&lt;p&gt;In regards to OpenIDConnect, there are a view parties that need to communicate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Resource Owner:&lt;/strong&gt; A user&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client:&lt;/strong&gt; A service (e.g. mycoolapp.com) that needs information&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authorization Server:&lt;/strong&gt; The identity provider of the resource server&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Server:&lt;/strong&gt; System containing information that the client needs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OpenIDConnect provides a set of standards that developers can use to connect various systems predictably:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scopes:&lt;/strong&gt; While OAuth defines scopes in an abstract sense, OIDC defines a standard set of scopes (openid, profile, email, and address).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claims:&lt;/strong&gt; Similarly, OIDC explicitly defines a set of claims that the scopes provide. These claims contain sets of user information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ID Token:&lt;/strong&gt; The ID Token contains information used to federate identity across applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;userinfo Endpoint:&lt;/strong&gt; OIDC defines a standard set of endpoints. The &lt;code&gt;/userinfo&lt;/code&gt; endpoint provides identity metadata verification to provide interoperability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JWTs:&lt;/strong&gt; OIDC utilizes the JSON Web Token (JWT) standard to sign the ID token, ensuring a cryptographically strong identity statement.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Centralized Identity Providers and SSO
&lt;/h2&gt;

&lt;p&gt;Authorization and Authentication protocols, such as those that we discussed previously, allow developers to separate their identity management systems from their applications. In this case, a single authentication source and user base can be used for a wide variety of applications. This is particularly useful in the enterprise environment, where users must access many resources but should not have independent user accounts for each service. Similarly, Authentication and Authorization can link many microservice to a single identity provider that is independent from the service itself, leading to a more loosely coupled application.&lt;/p&gt;

&lt;p&gt;In this series, we will be implementing &lt;a href="https://www.keycloak.org/" rel="noopener noreferrer"&gt;Keyloak&lt;/a&gt; as the bridge between a federated identity provider and our microservice applications. This will simplify the integration of additional microservices into our environment, as we will only need to interface with the identity provider once.&lt;/p&gt;

&lt;p&gt;Additionally, we will make use of a feature in Keycloak called roles. Roles are a specific tag assigned to users within Keycloak, and are passed to the application. Roles enable developers to define permission sets in their application for a given role, without considering the individual users that will assume that role.&lt;/p&gt;

&lt;h2&gt;
  
  
  High-Level Authentication Flow
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fmayormaier%2Fkeycloak-microservice-docs%2Fmain%2Fassets%2Fimages%2Ffull-flow.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fmayormaier%2Fkeycloak-microservice-docs%2Fmain%2Fassets%2Fimages%2Ffull-flow.jpg" alt="Authentication Flow with Keycloak"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The image above shows a high-level view of the authentication and authorization flow that we will build. Firstly, we will deploy the Keycloak server which will act as the SAML Service Provider and the OIDC Authentication Server. Next, we will configure the Keycloak server to use Azure Active Directory as the SAML IdP. This will enable users to log in to our applications. I will configure the microservice applications as OIDC clients. Because of the Single Sign On capability within Keycloak, authenticating once with the server will enable users to access all microservices on the page.&lt;/p&gt;

&lt;p&gt;As we progress in this series we will develop a pattern to integrate Keycloak into a micro-frontend service, with the goal of expanding authentiation to 10s of services on a single page. Follow along to learn more!&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.okta.com/identity-101/whats-the-difference-between-oauth-openid-connect-and-saml/" rel="noopener noreferrer"&gt;What’s the Difference Between OAuth, OpenID Connect, and SAML?&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.okta.com/blog/2020/09/what-is-saml/" rel="noopener noreferrer"&gt;What Is SAML and How Does It Work?&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.okta.com/openid-connect/" rel="noopener noreferrer"&gt;What is OpenID Connect?&lt;/a&gt;&lt;br&gt;
&lt;a href="https://developer.okta.com/blog/2017/06/21/what-the-heck-is-oauth" rel="noopener noreferrer"&gt;What the Heck is OAuth?&lt;/a&gt;&lt;br&gt;
&lt;a href="https://oauth.net/2/" rel="noopener noreferrer"&gt;OAuth2&lt;/a&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>microservices</category>
      <category>keycloak</category>
    </item>
    <item>
      <title>Using Vercel to instantly deploy web applications</title>
      <dc:creator>Andrew M</dc:creator>
      <pubDate>Mon, 14 Mar 2022 00:59:36 +0000</pubDate>
      <link>https://dev.to/mayormaier/using-vercel-to-deploy-applications-instantly-1c91</link>
      <guid>https://dev.to/mayormaier/using-vercel-to-deploy-applications-instantly-1c91</guid>
      <description>&lt;p&gt;Have you built a new web project recently and wanted to show it off to the world? Most likely, you run into this desire as a developer and discovered that the deployment process is long and laborious. Even &lt;em&gt;simple&lt;/em&gt; automation tools like &lt;a href=""&gt;GitHub Actions&lt;/a&gt; are riddled with complexity and can take a while to understand. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://vercel.com/docs" rel="noopener noreferrer"&gt;Enter Vercel&lt;/a&gt;&lt;/em&gt;, a platform as a service product that enables developers to showcase their projects &lt;strong&gt;with just a few clicks&lt;/strong&gt;. Oh, and its &lt;strong&gt;free&lt;/strong&gt; too, by the way. Today, I'll show you how you to leverage Vercel to deploy two styles of applications: a NodeJS application and an 11ty static site.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why use Vercel?
&lt;/h2&gt;

&lt;p&gt;In the world of application deployment, you may need to deal with servers, VMs, containers, Docker, networking, Terraform, AWS, Jenkins, Ansible...&lt;/p&gt;

&lt;p&gt;The list could go on forever.&lt;/p&gt;

&lt;p&gt;Vercel seeks to avoid complexity by abstracting away infrastructure entirely. It uses a &lt;em&gt;"Functions as a Service"&lt;/em&gt; or FaaS approach, which essentially means that you can upload your code (the &lt;em&gt;functions&lt;/em&gt;) and Vercel will build an environment around that. &lt;a href="https://aws.amazon.com/lambda/" rel="noopener noreferrer"&gt;If this sounds like AWS Lambda&lt;/a&gt;, that's because Vercel uses Lambda's engine under the hood to provide this functionality to its users. Vercel further abstracts Lambda's configuration process to provide an approachable environment to serverless compute.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started with Vercel
&lt;/h2&gt;

&lt;p&gt;The first logical step would be to create an account. As I mentioned previously, Vercel is incredibly easy to work with. Most developers use some type of version control (i.e., GitHub) during the development process, and Vercel integrates with many to connect your repositories right to their build pipeline. You can use GitHub, GitLab, or BitBucket to set up your account.&lt;/p&gt;

&lt;p&gt;After setting up your account, you're ready to start deploying your projects. From the Vercel dashboard, select the &lt;code&gt;New Project&lt;/code&gt; button. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b9dIQhzK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/wtR94Zw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b9dIQhzK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/wtR94Zw.png" alt="New Project button" width="800" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From there, you can take one of two paths: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Import a Git repository:&lt;/strong&gt; This is ideal for finished projects, or projects that you've already created a GitHub repository for. During the creation process, you'll create the first deployment of your app using the main branch of your repository. You don't need to use a specific framework for this method. &lt;strong&gt;Another consideration:&lt;/strong&gt; when connecting your account to version control, you are able to install Vercel across all public repositories on your account, or limit the installation to specific repositories. In the Vercel dashboard, You are only able to access projects that you have installed Vercel into.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clone Template:&lt;/strong&gt; This is ideal for new projects, after you've decided on a framework to use. Some available options are Next.js, Nuxt, 11ty, and Remix, amongst other options. Cloning a template will clone the starter project repository to your version control of choice, then install Vercel into that repository.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--z3TwHFgV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/QlOf4dJ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--z3TwHFgV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/QlOf4dJ.png" alt="Deployment options within Vercel" width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After selecting your path, you will be given some configuration options for the build/deployment of your application. When you're ready, select the blue &lt;code&gt;Deploy&lt;/code&gt; button, and you're off to the races! You'll see deployment progress, and a live output of the build right from the Vercel site.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SRn7xi8K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/lAuKxnr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRn7xi8K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/lAuKxnr.png" alt="Configuration options for a new Vercel project" width="671" height="976"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Environment variables:&lt;/strong&gt; Often, environment variables are required to store API Keys, database connection information, or other sensitive data. These values can be saved to Vercel via the "Environment Variables" section. If you need to add them after deployment, you can do so under &lt;code&gt;${Project} &amp;gt; Settings &amp;gt; Environment Variables&lt;/code&gt;. These values can then be accessed in code via &lt;code&gt;process.env.${variableName}&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  11ty on Vercel
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://11ty-hello-horses.vercel.app/" rel="noopener noreferrer"&gt;Example 1 - Hello Horses!&lt;/a&gt;&lt;br&gt;
&lt;a href="https://11ty-base-blog-three.vercel.app/" rel="noopener noreferrer"&gt;Example 2 - 11ty Base Blog&lt;/a&gt;&lt;br&gt;
&lt;a href="//11ty-hax11ty-blog.vercel.app"&gt;Example 3 - hax11ty&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Developers often leverage static site generators &lt;a href="//11ty.dev"&gt;(like 11ty)&lt;/a&gt; to spin up quick sites from template files, like markdown, that are easy to write. Left with these files, it can be a hassle to set up a web server, configure Nginx, copy the files, set up HTTPS, and configure a domain for the world to see. GitHub Pages helps to take away some of this configuration by automating the deployment process, but the configuration of GitHub Actions is still required, and some nice features like parallel preview builds are complex or missing. &lt;/p&gt;

&lt;p&gt;Vercel runs your &lt;code&gt;eleventy build&lt;/code&gt; command and completes all of the grunt work required to generate a public URL for the world to see with near zero configuration. It even allows users to deploy the same application from different branches so that new features can be test driven before production.&lt;/p&gt;

&lt;p&gt;One issue that I ran into was a configured &lt;code&gt;pathPrefix&lt;/code&gt; variable in my &lt;code&gt;.11ty.js&lt;/code&gt; configuration. This generated non-existent paths for my assets and links on the site. If you've deployed a site to GitHub pages, you likely have this configured. To solve this issue, I modified my &lt;code&gt;.11ty.js&lt;/code&gt; configuration to include the following in the &lt;code&gt;module.exports&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="c1"&gt;//support for deployment on both Vercel and GitHub Pages&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;deployPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deployEndpoint&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vercel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
      &lt;span class="nx"&gt;deployPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/11ty-base-blog/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, I set &lt;code&gt;module.exports&lt;/code&gt; to return &lt;code&gt;pathPrefix: deployPath&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I also included the &lt;code&gt;deployEndpoint&lt;/code&gt; environment variable and set it equal to &lt;code&gt;'vercel'&lt;/code&gt; in my deployment settings on Vercel.&lt;/p&gt;

&lt;h2&gt;
  
  
  NodeJS Applications on Vercel
&lt;/h2&gt;

&lt;p&gt;&lt;a href="//ist-vercel-demo-mayormaier.vercel.app"&gt;Example&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In addition to serving static content, Vercel provides server-side processing via Functions as a Service (FaaS). In the example above, the site utilizes micro-frontend components that process data via &lt;a href="https://vercel.com/docs/concepts/functions/introduction" rel="noopener noreferrer"&gt;Vercel's serverless functions.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Serverless functions in Vercel are created via files in the &lt;code&gt;/api&lt;/code&gt; directory of a project. There are &lt;a href="https://vercel.com/docs/concepts/functions/supported-languages#node.js" rel="noopener noreferrer"&gt;a number of supported backend languages, including JavaScript&lt;/a&gt;, which we used for this project. Within the file, a "handler" function is defined via the syntax below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Hello &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above function defines a handler &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RJqI1N22--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/5EZKNGM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RJqI1N22--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/5EZKNGM.png" alt="Viewing a function configuration on Vercel" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The image above shows a JavaScript function that defines a Serverless Function within Vercel. This function creates a HTTP endpoint at &lt;code&gt;domain.com/api/hello&lt;/code&gt;. This Function takes a query parameter of &lt;code&gt;name&lt;/code&gt;, and returns &lt;code&gt;Hello ${name}&lt;/code&gt; to the requesting client. &lt;/p&gt;

&lt;p&gt;No additional configuration was required to acheive this functionality, simply creating handler functions in the &lt;code&gt;/api/&lt;/code&gt; directory created the defined functions when the project was built and deployed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Case Study: Shoelace CSS on Vercel
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://mayormaier.github.io/cdn-workshop/" rel="noopener noreferrer"&gt;Mock Client&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/mayormaier/shoelace" rel="noopener noreferrer"&gt;Codebase&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vercel enables users to utilize &lt;em&gt;"preview branches"&lt;/em&gt; of their applications to test new features or application updates without pushing them to production. This is a feature not possible in simple deployment platforms like GitHub pages. Through this case study, I will demonstrate how to use preview branches when testing out changes to a web component library.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create a new branch in version control&lt;/strong&gt; Vercel automatically identifies your main branch in your version control platform. In this example, my main branch is called &lt;code&gt;main&lt;/code&gt; and my preview branch is called &lt;code&gt;mayormaier/future&lt;/code&gt;. &lt;a href="https://mayormaier.github.io/cdn-workshop/" rel="noopener noreferrer"&gt;This page&lt;/a&gt; shows components that are sourced from the &lt;code&gt;main&lt;/code&gt; (production) branch, served at &lt;code&gt;https://shoelace-mayormaier.vercel.app&lt;/code&gt;. Vercel treats &lt;strong&gt;all&lt;/strong&gt; other branches in version control as preview branches.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Push changes to the new branch&lt;/strong&gt; When changes are pushed to non-main branches, &lt;code&gt;mayormaier/future&lt;/code&gt; in this case, a &lt;em&gt;preview deployment&lt;/em&gt; is created.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EHcHQ5rP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/iksFRJQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EHcHQ5rP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/iksFRJQ.png" alt="preview deployment in the Vercel dashboard" width="800" height="194"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because any non-main branch can trigger a preview deployment, one application can have seemingly endless numbers of preview deployments, each to test out new features. In this example, &lt;a href="//shoelace-git-mayormaier-future-mayormaier.vercel.app"&gt;the preview deployment is found here&lt;/a&gt;. It is also referenced on &lt;a href="https://mayormaier.github.io/cdn-workshop/in-the-future" rel="noopener noreferrer"&gt;this page&lt;/a&gt;, where the script tags in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; of the page reference the preview deployment. Notice the underlined text in the components, the "new feature" that we wanted to test drive.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt;
    &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt;
    &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://shoelace-git-mayormaier-future-mayormaier.vercel.app/themes/dark.css"&lt;/span&gt;
    &lt;span class="na"&gt;onload=&lt;/span&gt;&lt;span class="s"&gt;"document.documentElement.classList.add('sl-theme-dark');"&lt;/span&gt;
    &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://shoelace-git-mayormaier-future-mayormaier.vercel.app/shoelace.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Ship applications at blazing speeds with Vercel, a service that abstracts much of the configuration details away for their Serverless Functions. Use of vercel is free for most "Hobby" use cases, however &lt;a href="https://vercel.com/docs/concepts/limits/overview" rel="noopener noreferrer"&gt;it is subject to certain limits on  execution time and bandwidth&lt;/a&gt;. Enterprise applications may need additional firepower or control. Vercel has a paid tier that unlocks additional performance, but for fine grained control configuring AWS Lambda yourself may be necessary.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>devops</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Architecting Portable Applications with Docker</title>
      <dc:creator>Andrew M</dc:creator>
      <pubDate>Mon, 28 Feb 2022 07:34:10 +0000</pubDate>
      <link>https://dev.to/mayormaier/architecting-portable-applications-with-docker-41oe</link>
      <guid>https://dev.to/mayormaier/architecting-portable-applications-with-docker-41oe</guid>
      <description>&lt;p&gt;&lt;em&gt;"But it works on my machine!"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Thats the endless cry of developers working on a team and developing in different environments. There's always one that just can't get the program to run, no matter what they try.&lt;/p&gt;

&lt;p&gt;Sure, this problem is unfortunate, but what's worse is deploying applications across inconsistent environments. The more that an application must scale, the larger chance there is for inconsistency.&lt;/p&gt;

&lt;p&gt;Enter Docker- a &lt;strong&gt;containerization&lt;/strong&gt; platform that obliterates the problem of inconsistent environments and also provides other benefits like a smaller footprint compared to VM deployments. &lt;/p&gt;

&lt;h2&gt;
  
  
  What is a container?
&lt;/h2&gt;

&lt;p&gt;A container is a &lt;a href="https://www.docker.com/resources/what-container" rel="noopener noreferrer"&gt;standardized compute environment&lt;/a&gt; (like a Virtual Machine) that only contains the libraries and components that an application needs to run. Containers have a smaller footprint because they do not run their own kernel, but instead connect to the host's kernel through the containerd runtime.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Di5zmIj7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.docker.com/sites/default/files/d8/styles/large/public/2018-11/container-what-is-container.png%3Fitok%3Dvle7kjDj" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Di5zmIj7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.docker.com/sites/default/files/d8/styles/large/public/2018-11/container-what-is-container.png%3Fitok%3Dvle7kjDj" alt="Thank you Docker for this great diagram of a container!" width="800" height="693"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How are containers so portable?
&lt;/h2&gt;

&lt;p&gt;Containers can be hardened into images that can be replicated across machines, but it is the automated build process that truly makes containers rock.&lt;/p&gt;

&lt;p&gt;When software is ready for deployment, it can be run through an image build pipeline, where a standardized set of commands (a &lt;a href="https://docs.docker.com/engine/reference/builder/" rel="noopener noreferrer"&gt;Dockerfile&lt;/a&gt;) can be run to produce a container image.&lt;/p&gt;

&lt;p&gt;This is an example of a Dockerfile used to build a NodeJS backend application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:12&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /home/node/app&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;yarn &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; [ "yarn", "start" ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What do all of those commands mean?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;FROM&lt;/em&gt;: This Dockerfile builds an application backend on top of a nodejs 12 base image&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;WORKDIR&lt;/em&gt;: This changes the working directory of the build process&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;COPY&lt;/em&gt;: This copies files from the host computer into the container as it is being built&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;RUN&lt;/em&gt;: This executes a command within the container itself (i.e., to install the required packages in this case)&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;CMD&lt;/em&gt;: This provides a command that will be run when the container is started&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, when building a container image through a Dockerfile, it is important to think about a few things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What software do I need on my container? This will determine your base image (node, mysql, python, etc.)&lt;/li&gt;
&lt;li&gt;What files do I need to copy to my container?&lt;/li&gt;
&lt;li&gt;Do I need to run any commands to build my software?&lt;/li&gt;
&lt;li&gt;What command or process do I want to start when the container runs?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After considering these questions, you will have enough information to build your container through a Dockerfile. Regardless of the environment or application, these principals can be applied to produce a standardized image that will run anywhere.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>tooling</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to build powerful sites from scratch with 11ty</title>
      <dc:creator>Andrew M</dc:creator>
      <pubDate>Mon, 28 Feb 2022 02:38:11 +0000</pubDate>
      <link>https://dev.to/mayormaier/how-to-build-powerful-sites-from-scratch-with-11ty-1lpa</link>
      <guid>https://dev.to/mayormaier/how-to-build-powerful-sites-from-scratch-with-11ty-1lpa</guid>
      <description>&lt;p&gt;If you've been interested in the web space recently, you've heard of static site generators like 11ty and Jekyll. These pieces of software take easily written markup such as markdown, nunjucks, and liquid and turn them into content that is ready for the web. Many developers want to author blog posts for their own site, and 11ty provides a way to do just that.&lt;/p&gt;

&lt;p&gt;While on the surface it seems simple, theres a lot under the hood that makes 11ty a machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Terms
&lt;/h2&gt;

&lt;p&gt;Before starting, it's important to know terms that 11ty uses to describe their files. The names sound similar, but the differentiations are important.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;template&lt;/strong&gt; - a file that contains content (written in a language like markdown)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;layout&lt;/strong&gt; - pre-built wrappers for templates. Used to define a common structure for a set of templates/pages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;front matter&lt;/strong&gt; - key-value pairs at the top of a template that define specific variables that are used when rendering pages in 11ty&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;data file&lt;/strong&gt; - purpose built files that define variables to be inherited by all templates in a defined directory.

&lt;ul&gt;
&lt;li&gt;Ex. in the directory &lt;code&gt;/posts&lt;/code&gt;, &lt;code&gt;/posts/posts.json&lt;/code&gt; would be the directory data file, and would define variables that all other template files &lt;code&gt;/posts/*&lt;/code&gt; should inherit.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;11ty can be intimidating at first, especially if you are new to command line tooling. To start, I followed the great getting started guide at &lt;/p&gt;

&lt;p&gt;Here, I will demonstrate three ways to build an 11ty site, both using templates and from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 1: &lt;a href="https://mayormaier.github.io/11ty-hello-horses/" rel="noopener noreferrer"&gt;From scratch&lt;/a&gt;
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Shameless plug, I heavily leaned on the &lt;a href="https://www.youtube.com/watch?v=PPZGdolA_ns&amp;amp;t=7001s" rel="noopener noreferrer"&gt;great tutorial&lt;/a&gt; by &lt;a href="https://twitter.com/trostcodes?lang=en" rel="noopener noreferrer"&gt;Alex Trost&lt;/a&gt; and &lt;a href="https://twitter.com/BenDMyers" rel="noopener noreferrer"&gt;Ben Meyers&lt;/a&gt; when completing this project.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One nice thing about 11ty is that you can start out VERY basic, then build up in complexity.&lt;br&gt;
To start,&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;initialize a new npm package &lt;code&gt;npm init&lt;/code&gt; and install 11ty &lt;code&gt;npm install @11ty/eleventy&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;create some template files &lt;code&gt;somethingCool.md&lt;/code&gt; and throw them in the project root&lt;/li&gt;
&lt;li&gt;run &lt;code&gt;npx eleventy --serve&lt;/code&gt; and watch your templates turn into HTML in the &lt;code&gt;_site&lt;/code&gt; directory&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now lets kick it up a notch.&lt;br&gt;
First lets provide some organization to our project.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;create an &lt;code&gt;.eleventy.js&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;add &lt;code&gt;return { dir: { input: "src" } };&lt;/code&gt; in a new &lt;code&gt;module.exports()&lt;/code&gt; function
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;embeds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eleventy-plugin-embed-everything&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eleventyConfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;eleventyConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addPlugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;embeds&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;eleventyConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addWatchTarget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;_site/assets/*.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;eleventyConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setBrowserSyncConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;_site/assets/*.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;An example &lt;code&gt;.eleventy.js&lt;/code&gt; file. NOTE: this file contains additional plug in modules that you probably don't have installed yet. Only use this configuration if you have the defined modules installed.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;create a new directory called &lt;code&gt;src&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;move your precious templates to the new &lt;code&gt;src&lt;/code&gt; directory&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, lets add some additional structure to our pages. When eleventy builds a page, it focuses on minimal HTML. No &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; information is included.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;in your &lt;code&gt;src&lt;/code&gt; directory, add a &lt;code&gt;_includes&lt;/code&gt; subdirectory. This is where you will store your layout files.&lt;/li&gt;
&lt;li&gt;create a new layout file. you can specify where the content should be inserted with &lt;code&gt;{{content}}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;specify this layout to be used in the front matter of a template using the &lt;code&gt;layout&lt;/code&gt; key:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;layout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;layoutFilename&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="p"&gt;-&lt;/span&gt; cool
&lt;span class="p"&gt;-&lt;/span&gt; markdown
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Lastly, lets add a plugin to this site. We will be installing the &lt;a href="https://www.npmjs.com/package/eleventy-plugin-embed-everything" rel="noopener noreferrer"&gt;eleventy-embed-everything&lt;/a&gt; plugin.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;install the plugin with &lt;code&gt;npm install eleventy-plugin-embed-everything --save&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;add the plugin to the &lt;code&gt;.eleventy.js&lt;/code&gt; file
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;embedEverything&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eleventy-plugin-embed-everything&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eleventyConfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;eleventyConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addPlugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;embedEverything&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now you can embed media into the page simply by dropping its url on to the page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.11ty.dev/docs/getting-started/" rel="noopener noreferrer"&gt;More information&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/mayormaier/11ty-hello-horses" rel="noopener noreferrer"&gt;Source repository&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Method 2: &lt;a href="https://mayormaier.github.io/11ty-base-blog/" rel="noopener noreferrer"&gt;Based on a template&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The 11ty community has developed a plethora of templates that accomplish the initial configuration of 11ty quite well. Many of these sites contain a lot of useful tools and features, but on occasion this can bloat the final size of the project. The output files however remain flat and slender.&lt;/p&gt;

&lt;p&gt;The first step that I took when configuring this template was to modify the metadata of the site to match my details (name, url, email, etc.)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PPqygpF4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/ww1RrOT.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PPqygpF4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/ww1RrOT.png" alt="Modified configuration items" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, I modified the pathPrefix variable in the &lt;code&gt;.eleventy.js&lt;/code&gt; file. This allows the site to be deployed to GitHub pages without explicitly defining the pathPrefix in page links (which would break the site in development).&lt;/p&gt;

&lt;p&gt;Lastly, I added my articles to the &lt;code&gt;/posts/&lt;/code&gt; directory. Because much of the configuration has already been completed, it is pretty much plug and play for all of the articles. If additional subdirectories/categories are desired, more configuration is necessary.&lt;/p&gt;

&lt;p&gt;After inserting my articles, I specified some template metadata for each article. These vary slightly from the custom built template as different data variables are used, however they generally accomplish the same thing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oKoplKoX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/el03eOF.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oKoplKoX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/el03eOF.png" alt="Template data in the front matter" width="688" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://eleventy-base-blog.netlify.app/" rel="noopener noreferrer"&gt;More Information&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/mayormaier/11ty-base-blog" rel="noopener noreferrer"&gt;Source Repository&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Method 3: &lt;a href="https://mayormaier.github.io/11ty-hax11ty-blog/" rel="noopener noreferrer"&gt;hax11ty&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;hax11ty combines the powerful library of web components found in HAXCMS with the simplicity of static sites. Just like 11ty, it takes in template files, and outputs them as HTML. Just like in Method 2, utilizing a pre-built 11ty configuration saves a lot of time when you need to get a site off the ground quickly. With a clean theme and the addition of web components, hax11ty takes static sites to the next level.&lt;/p&gt;

&lt;p&gt;For example, adding the &lt;code&gt;&amp;lt;video-player&amp;gt;&lt;/code&gt; tag to our markdown yields a rendered video-player component on the page.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt; things
&lt;span class="p"&gt;-&lt;/span&gt; and
&lt;span class="p"&gt;-&lt;/span&gt; stuff

&lt;span class="nt"&gt;&amp;lt;video-player&lt;/span&gt; &lt;span class="na"&gt;source=&lt;/span&gt;&lt;span class="s"&gt;"https://www.youtube.com/watch?v=dQw4w9WgXcQ"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/video-player&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ppqh0uL_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/oTX4MeQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ppqh0uL_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/oTX4MeQ.png" alt="Page with the rendered video-player component" width="800" height="638"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Structure
&lt;/h2&gt;

&lt;p&gt;When using 11ty, there is a clear division between source content and static HTML site files. 11ty will locate the content for your site, written in any of the supported templating languages, then convert it into HTML and place it into the &lt;code&gt;_site&lt;/code&gt; directory. Within the &lt;code&gt;_site&lt;/code&gt; directory, there is an exact clone of the directory structure where all of the source files lived previously. This &lt;code&gt;_site&lt;/code&gt; directory is key, because this is the directory that includes the HTML files needed to power a website. The &lt;code&gt;_site&lt;/code&gt; directory can be zipped and uploaded to a website hosting platform.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0V-85WUA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/cAx5e8J.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0V-85WUA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/cAx5e8J.png" alt="Template files (source)" width="189" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gNo6cg8Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/D4gpoxf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gNo6cg8Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/D4gpoxf.png" alt="Output files" width="200" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These HTML files are generated through a process that 11ty calls &lt;strong&gt;&lt;a href="https://www.11ty.dev/docs/data-cascade/" rel="noopener noreferrer"&gt;the data cascade&lt;/a&gt;&lt;/strong&gt; The data cascade dictates the order of priority for sources of layout and style data for the static HTML files. While extremely technical, the cascade basically begins by applying global data to the template files, and then overwrites these data files as it moves deeper into the directory. Data files with the same name and same directory as the templating files are given the highest priority.&lt;/p&gt;

&lt;p&gt;Lastly, the YAML front matter in each templating file is applied, which overwrites values further up in the data cascade. This is helpful for applying specific properties, such as a permalink, to individual files.&lt;/p&gt;

&lt;p&gt;When a website goes live, the folder structure that contains the markdown files transfers directly to the generated static HTML files. So, for example, if a particular markdown file is located at &lt;code&gt;/src/welcome.md&lt;/code&gt; then the subsequent HTML file will appear at &lt;code&gt;_site/src/welcome/index.html&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One caveat to 11ty is that it does not automatically copy non-supported file types (anything other than files written in the supported templating languages) into the &lt;code&gt;_site&lt;/code&gt; directory. In order to request that these files are copied into the &lt;code&gt;_site&lt;/code&gt; directory, use the &lt;code&gt;--formats =&lt;/code&gt; flag on the command line to specify certain file types.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://elmsln.github.io/hax11ty/" rel="noopener noreferrer"&gt;More information&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/mayormaier/11ty-hax11ty-blog" rel="noopener noreferrer"&gt;Source Repo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>web</category>
      <category>jamstack</category>
      <category>tutorial</category>
      <category>11ty</category>
    </item>
    <item>
      <title>Integrating APIs with JavaScript in the Front End</title>
      <dc:creator>Andrew M</dc:creator>
      <pubDate>Sun, 30 Jan 2022 22:36:26 +0000</pubDate>
      <link>https://dev.to/mayormaier/integrating-apis-with-javascript-in-the-front-end-2leo</link>
      <guid>https://dev.to/mayormaier/integrating-apis-with-javascript-in-the-front-end-2leo</guid>
      <description>&lt;h2&gt;
  
  
  Fetch and the Power of APIs
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;fetch()&lt;/code&gt; is an &lt;em&gt;asynchronous&lt;/em&gt; JavaScript function that allows client-side web applications to make HTTP Requests to a web endpoint. This is most commonly used to make API calls from the browser.&lt;/p&gt;

&lt;p&gt;Asynchronous functions are known as "non-blocking". Rather than taking up a processing thread while waiting for a return value, non-blocking functions allow other operations to execute in the program. This results in much more responsive applications. &lt;/p&gt;

&lt;p&gt;Fetch's asynchronous property is enables it to free the processing thread while waiting for an API response. This is a great way of handing API calls, as responses can vary in speed depending on the destination server and application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://example.com/movies.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;the above example is courtesy of Mozilla&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The fetch method is relatively simple. In its most basic form, &lt;code&gt;fetch()&lt;/code&gt; has one parameter, the URL of the HTTP endpoint. Other parameters can be added to send data to an endpoint (i.e., JSON for a HTTP PUT request). This enables developers to fully leverage API requests in their front end applications. &lt;/p&gt;

&lt;p&gt;In the example above, an HTTP GET request was made, which returns data from the server to the client. After the response returns successfully, the &lt;code&gt;.then()&lt;/code&gt; functions parse the response as JSON, then print it to the console. However, console logging is not the only thing that can be accomplished in this function. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;.then()&lt;/code&gt; clauses can also be used to pull data from the API response and set it as a variable. For example, in the application presented in this example, the responses from  &lt;a href="https://www.freegeoip.app/json" rel="noopener noreferrer"&gt;freegeoip.app/json&lt;/a&gt; are used to identify the location of a user at a specific IP address. The &lt;code&gt;latitude&lt;/code&gt; &lt;code&gt;longitude&lt;/code&gt; &lt;code&gt;city&lt;/code&gt; and &lt;code&gt;region_name&lt;/code&gt; fields are all variables that the API returns and are tracked by the application. Here's an example of the JSON data returned by the API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"ip"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"104.38.28.100"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"country_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"US"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"country_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"United States"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"region_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"region_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Pennsylvania"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"University Park"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"zip_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"16802"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"time_zone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"America/New_York"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"latitude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"longitude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;-77&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"metro_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;574&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;This JSON blob is sample API response from the &lt;a href="https://www.freegeoip.app/json" rel="noopener noreferrer"&gt;freegeoip.app/json&lt;/a&gt; API.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Element Variables and Rendering
&lt;/h2&gt;

&lt;p&gt;Variable assignment in the &lt;code&gt;then()&lt;/code&gt; method calls enables stateful updating of the application. Each time that the API is called and returns data successfully, the instance variables are updated, and the DOM is re-painted with the new data. The render() function determines how the page will be displayed each time that the DOM is painted. Not all variables in the application achieve this behavior- only variables defined in the &lt;code&gt;static get properties()&lt;/code&gt; method trigger the DOM to be re-painted. Note: you can also generate new variables based on the variables that are returned by an API call. For example, I set location equal to &lt;code&gt;$city, $region_name&lt;/code&gt; which is used many other times in the application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;reflect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;long&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;reflect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;reflect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;reflect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;reflect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;The properties defined in this method trigger the DOM to be re-painted&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let's discuss the &lt;code&gt;&amp;lt;location-from-ip&amp;gt;&lt;/code&gt; component in more depth. Firstly, the properties listed above populate the component with the data that it needs to render. The data relies on APIs to populate. The &lt;code&gt;getGEOIPData()&lt;/code&gt; function includes all of the logic to obtain these data points.&lt;/p&gt;

&lt;p&gt;Firstly, a &lt;code&gt;UserIP&lt;/code&gt; object instance is created to identify the IP address of the user. This relies on an API that returns the IP of the user making the request. This IP addres data is then fed into another API (&lt;a href="https://www.freegeoip.app/" rel="noopener noreferrer"&gt;freegeoip.app&lt;/a&gt;) that takes the IP address from the user and returns location data about that IP address. See the example API response above. After the response is retuned, the given variables are updated which triggers a repainting of the DOM. This update feeds those new variables into a number of services defined in the &lt;code&gt;render()&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://maps.google.com/maps?q=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;long&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;t=&amp;amp;z=15&amp;amp;ie=UTF8&amp;amp;iwloc=&amp;amp;output=embed`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`
      &amp;lt;iframe title="Where you are" src="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;&amp;lt;/iframe&amp;gt;
      &amp;lt;br /&amp;gt;&amp;lt;a
        href="https://www.google.com/maps/@&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;long&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,15z"
        target="_blank"
        &amp;gt;Expand Map to &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/a
      &amp;gt;
      &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;
      &amp;lt;wikipedia-query search="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;&amp;lt;/wikipedia-query&amp;gt;
      &amp;lt;wikipedia-query search="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;&amp;lt;/wikipedia-query&amp;gt;
      &amp;lt;wikipedia-query search="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;region&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;&amp;lt;/wikipedia-query&amp;gt;
    `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;lat&lt;/code&gt; and &lt;code&gt;long&lt;/code&gt; variables are inserted into an Google Maps embed link that populates an &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;lat&lt;/code&gt;, &lt;code&gt;long&lt;/code&gt; and &lt;code&gt;location&lt;/code&gt; variables are used to populate a hyperlink that opens the location in the full Google Maps site. &lt;/li&gt;
&lt;li&gt;The &lt;code&gt;&amp;lt;wikipedia-query&amp;gt;&lt;/code&gt; web component is leveraged to provide articles about the location determined by the GEOIP API. The compnent relies on a &lt;code&gt;search&lt;/code&gt; property that defines the wikipedia page to display. There are three &lt;code&gt;&amp;lt;wikipedia-query&amp;gt;&lt;/code&gt; tags total. One uses the &lt;code&gt;location&lt;/code&gt; property as the search string, and the other two use &lt;code&gt;city&lt;/code&gt; and &lt;code&gt;region&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftqtzywaadnkkyumy56ri.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftqtzywaadnkkyumy56ri.png" alt="Image description" width="800" height="674"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The &lt;code&gt;&amp;lt;location-from-ip&amp;gt;&lt;/code&gt; element, visually&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ultimately, the use of APIs within web components can be achieved with ease and is a great way to add responsive elements to a static site.&lt;/p&gt;

&lt;p&gt;For more information about the API used in this application, see &lt;a href="https://www.freegeoip.app/" rel="noopener noreferrer"&gt;freegeoip.app&lt;/a&gt;, &lt;a href="https://codepen.io/btopro/pen/yLNmVbw" rel="noopener noreferrer"&gt;wikipedia element&lt;/a&gt;, &lt;a href="https://ip-fast.com/api/ip/" rel="noopener noreferrer"&gt;IPFast IP Address API&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href="https://github.com/mayormaier/API-Project/blob/master/src/LocationFromIP.js" rel="noopener noreferrer"&gt;application repository here&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Sources
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Concepts" rel="noopener noreferrer"&gt;General asynchronous programming concepts - MDN Web Docs&lt;/a&gt;&lt;br&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch" rel="noopener noreferrer"&gt;Using Fetch - MDN Web Docs&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>api</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Getting Started with open-wc and Web Components</title>
      <dc:creator>Andrew M</dc:creator>
      <pubDate>Sat, 15 Jan 2022 22:49:16 +0000</pubDate>
      <link>https://dev.to/mayormaier/getting-started-with-open-wc-and-web-components-1e16</link>
      <guid>https://dev.to/mayormaier/getting-started-with-open-wc-and-web-components-1e16</guid>
      <description>&lt;p&gt;&lt;em&gt;One month ago, I hadn't written a single line of JavaScript.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I knew that JavaScript was important, but I seemed to be scared away by the massive ecosystem. As I looked deeper into the powerful things that you can do with JavaScript, I knew I had to get my feet wet. If you're looking to get started with open-wc and Web Components, you're going to need to understand the fundamentals of plain vanilla JavaScript. That might sound daunting, but &lt;strong&gt;getting started with Javascript is easier than you think.&lt;/strong&gt; Today I'll show you why.&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript Basics
&lt;/h2&gt;

&lt;p&gt;Before starting my journey with JavaScript I had intermediate programming experience. Most of my academic career I have used Java, and I've written my personal projects in python. If you've never written &lt;em&gt;any&lt;/em&gt; code, thats ok. We all start somewhere. Most language fundamental tutorials are beginner friendly.&lt;/p&gt;

&lt;p&gt;From a JavaScript newbie, &lt;strong&gt;I recommend the &lt;a href="https://www.linkedin.com/learning-login/share?account=76811570&amp;amp;forceAccount=false&amp;amp;redirect=https%3A%2F%2Fwww.linkedin.com%2Flearning%2Fjavascript-essential-training%3Ftrk%3Dshare_ent_url%26shareId%3DtagQlFJZTBmp1uXvG335Dw%253D%253D" rel="noopener noreferrer"&gt;JavaScript Essential Training LinkedIn Learning Course&lt;/a&gt;.&lt;/strong&gt; This course helped me to get an understanding od the language as a whole while also understanding the JavaScript ecosystem. I'm about 30% of the way through it, and plan on banging out some more after I finish this article.&lt;/p&gt;

&lt;p&gt;One more thing- one of the biggest surprises for me is that &lt;strong&gt;JavaScript's native runtime is in the browser&lt;/strong&gt; (Like Google Chrome). It took some getting used to, as I was more familiar with working completely in the command line. It is intuitive though, as a majority of JavaScript use cases involve the web in some capacity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparing the JavaScript Environment
&lt;/h2&gt;

&lt;p&gt;Unlike many languages (like Python, Java, and Go), you don't need to download a language interpreter to your machine. In fact, you run JavaScript code every time you visit &lt;em&gt;most&lt;/em&gt; websites. So, if you have a modern web browser installed, then you're golden.&lt;/p&gt;

&lt;h3&gt;
  
  
  VS Code
&lt;/h3&gt;

&lt;p&gt;I use Visual Studio Code to write my JavaScript Code. It is very lightweight bare bones out of the box, but it has a rich extension ecosystem that you can use to increase its functionality. &lt;/p&gt;

&lt;p&gt;Head over to &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;code.visualstudio.com&lt;/a&gt; to install VS Code. Click on the big blue installation button to download the installer and follow the prompts when running it.&lt;/p&gt;

&lt;p&gt;One key extension that you will need when writing and testing vanilla JS is "Live Server". This allows users to start a local web server for their current VS Code project with just one click.&lt;/p&gt;

&lt;h3&gt;
  
  
  Node.js
&lt;/h3&gt;

&lt;p&gt;The next step is to download Node.JS. You want to get the current LTS (Long Term Support) version for increased stability. To install, head to &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;nodejs.org&lt;/a&gt; and click the nice big green "LTS" button. The site should recognize the OS that you are working with and give you the right installer.&lt;/p&gt;

&lt;p&gt;Node.JS enables you to run server-side JavaScript applications on your machine. Some people think that Node.JS is a JavaScript library or a framework or its own separate language, but &lt;strong&gt;Node.JS is none of those. Node.JS is a runtime for JavaScript.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After running the installer, check that Node.js was installed properly with &lt;code&gt;node -v&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnjdfut6p7hnara15c1is.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnjdfut6p7hnara15c1is.png" alt="node -v output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  npm
&lt;/h3&gt;

&lt;p&gt;Node comes with a package manager for JavaScript called &lt;a href="https://npmjs.com/" rel="noopener noreferrer"&gt;npm&lt;/a&gt;. npm enables you to use other people's code in your projects without needing to go and write it yourself. Users can find npm packages on the npm registry, then use them in their code by using the Node require() function and defining them in their projects' &lt;code&gt;package.json&lt;/code&gt; file, creating a dependency. All of this can sound confusing at first, but for now, just know that you can piggyback off of other projects with npm.&lt;/p&gt;

&lt;p&gt;To verify that npm was installed correctly when you installed Node.js, you can run &lt;code&gt;npm -v&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4vxheujhvs0mzp23ec19.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4vxheujhvs0mzp23ec19.png" alt="npm -v output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Yarn
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://yarnpkg.com" rel="noopener noreferrer"&gt;Yarn&lt;/a&gt; is another package manager for JavaScript. It is very similar to npm as it enables users to reuse code from other developers by helping them register dependencies in their project. It registers dependencies to the &lt;code&gt;package.json&lt;/code&gt; just like npm.&lt;/p&gt;

&lt;p&gt;With newer versions of Node, yarn comes pre-installed and can be installed without much hassle. Simply run &lt;code&gt;corepack enable&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After doing this, you can verify that yarn is installed properly with &lt;code&gt;yarn -v&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkvilukqczym3hsfmtwlo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkvilukqczym3hsfmtwlo.png" alt="varn -v output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Initializing an open-wc starter project
&lt;/h2&gt;

&lt;p&gt;Now that the basic software is installed and running, a new open-wc component can be created. This process is also relatively simple. First, create a new directory where your project will live and navigate to it. Then, run &lt;code&gt;npm init @open-wc&lt;/code&gt; If the command runs successfully, that means that you've installed everything correctly and you are beginning to work on your first web component!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faauwov28d7m9coqn8kz5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faauwov28d7m9coqn8kz5.png" alt="Shows expected output of the initialization for open-wc"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the screen that you will see with instructions to set up the project.&lt;/p&gt;

&lt;p&gt;I've initialized my starter project with the following settings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New project scaffold&lt;/li&gt;
&lt;li&gt;Web Component&lt;/li&gt;
&lt;li&gt;Linting, Testing, and Demoing enabled&lt;/li&gt;
&lt;li&gt;No TypeScript&lt;/li&gt;
&lt;li&gt;installed using yarn&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once these settings are selected, a browser window should open and connect to the Node web server that is serving the project. If that does not happen automatically, or you want to start up the server at a later date, simply run &lt;code&gt;npm start&lt;/code&gt;. Boom! Now you can take a look at how web components work on the web.&lt;/p&gt;

&lt;h2&gt;
  
  
  Analyzing a Web Component
&lt;/h2&gt;

&lt;p&gt;Web Components, even in their most simple form have numerous files that provide functionality. Each of these files has a unique purpose that enables web components to function as the easy to use, reusable HTML elements.&lt;/p&gt;

&lt;p&gt;First, lets look at the &lt;code&gt;index.html&lt;/code&gt; of this project, the file that the browser loads when this project is opened.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"demo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../hello-world.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello World!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// takes elements with id=demo and replaces with hello-world element&lt;/span&gt;
    &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`
        &amp;lt;hello-world .title=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;
          some light-dom
        &amp;lt;/hello-world&amp;gt;
      `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#demo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this file, there is a div with id=demo, that is then replaced by the &lt;code&gt;&amp;lt;hello-world&amp;gt;&lt;/code&gt; element when the script is loaded. The &lt;code&gt;&amp;lt;hello-world&amp;gt;&lt;/code&gt; element is hydrated with content referenced in &lt;code&gt;hello-world.js&lt;/code&gt;, which is imported to the script.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// imports the HelloWorld class from the source files&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HelloWorld&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/HelloWorld.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// defines the "&amp;lt;hello-world&amp;gt;" HTML tag from the HelloWorld class in the imported module&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello-world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HelloWorld&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;hello-world.js&lt;/code&gt; defines the &lt;code&gt;&amp;lt;hello-world&amp;gt;&lt;/code&gt; HTML tag with the HelloWorld Web Component.&lt;/p&gt;

&lt;p&gt;The meat of the element is found in &lt;code&gt;./src/HelloWorld.js&lt;/code&gt;. This component defines the functions and properties of the HelloWorld web component, represented as a class that extends the base HelloWorld class. For example, one of the functions called &lt;code&gt;__increment()&lt;/code&gt; increments the counter property of the HelloWorld object every time a button in the component is pressed.&lt;/p&gt;

&lt;p&gt;Many of the other files that come with the base "hello-world" web component serve important purposes also. I've annotated many of the files found in this project and &lt;a href="https://github.com/mayormaier/edtechjoker-lab1/" rel="noopener noreferrer"&gt;uploaded them to a GitHub repository that can be found here.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>webcomponents</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Vaccines for Common SQL Injection Bugs</title>
      <dc:creator>Andrew M</dc:creator>
      <pubDate>Fri, 25 Sep 2020 19:06:15 +0000</pubDate>
      <link>https://dev.to/mayormaier/vaccines-for-common-sql-injection-bugs-20d</link>
      <guid>https://dev.to/mayormaier/vaccines-for-common-sql-injection-bugs-20d</guid>
      <description>&lt;p&gt;&lt;em&gt;I chose to connect SQL to the Web through option 2, a more SRA/ security-based approach&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;SQL Injection is one of the most common web hacking techniques (w3schools.com). In cases where SQL databases are queried by site visitors, these injections pose a big threat to the database. SQL injections allow a user to send malicious code to a database by inserting a SQL command into a web input field. Without proper defense against them, websites can be left vulnerable, and massive data leaks can occur as a result.&lt;/p&gt;

&lt;p&gt;Below, I take a look at some of the most common SQL injection &lt;/p&gt;

&lt;h2&gt;
  
  
  1=1
&lt;/h2&gt;

&lt;p&gt;One of the most common approaches to SQL injection is the 1=1 method. This is often used to gain unauthorized access to a user account. In this case, a false password is entered into the password field, followed by a quote mark and &lt;code&gt;OR 1=1--&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This allows the unauthorized user to bypass the password field of the login page, because the database reads that it is supposed to allow a login &lt;code&gt;WHERE Password = ... OR 1=1&lt;/code&gt; Because 1=1 is always true, the user will be allowed in and the rest of the line is commented out. &lt;/p&gt;

&lt;h2&gt;
  
  
  Batched Statements
&lt;/h2&gt;

&lt;p&gt;Another common SQL Injection is the batched statement. These injections finish a legitimate statement with a semicolon &lt;strong&gt;;&lt;/strong&gt; before executing their malicious statement. For example, if a user enters details into a search box, and the search is selecting some information where a condition is true, after giving the parameter, a user can insert their malicious code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exploitation through URL
&lt;/h2&gt;

&lt;p&gt;Lastly, if a user can see part of an SQL query via the URL for example &lt;code&gt;http://widgetshop.com/widget/?id=1&lt;/code&gt;, they are able to understand how the query is formed in order to change manipulate the URL and create malicious queries. In this case, the user can easily append additional SQL statements to the end of the query for example &lt;code&gt;...OR 1=1&lt;/code&gt; and see more data than intended. &lt;/p&gt;

&lt;h2&gt;
  
  
  Solutions
&lt;/h2&gt;

&lt;p&gt;Clearly, using user input to craft SQL Queries is a big vulnerability. Thus, finding a way to protect your database from malicious requests is essential to maintaining data security. In order to avoid malicious input to your site, you need to use one (&lt;em&gt;or many&lt;/em&gt;) abstractions so that only valid input is accepted into the SQL command.&lt;/p&gt;

&lt;p&gt;One abstraction that can be used to solve this issue is to parameterize the SQL statements outbound for the database so that they are treated properly. In order to do this, the SQL statement string and its associated input parameters are passed to the database separately which allows the database to properly interpret the command. Each parameter has a defined variable type, so the input is sanitized. This is opposed to the full SQL command being constructed on the front end of the website, making it vulnerable to malicious parameters.  &lt;/p&gt;

&lt;p&gt;To see how these SQL injections can be used for malicious purposes, check out the video below. &lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/obzeB7jttSU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>security</category>
      <category>sql</category>
      <category>database</category>
    </item>
  </channel>
</rss>
