<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.2.2">Jekyll</generator><link href="https://dovidkopel.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://dovidkopel.com/" rel="alternate" type="text/html" /><updated>2025-10-22T19:02:45+00:00</updated><id>https://dovidkopel.com/feed.xml</id><title type="html">Dovid Kopel - Technologist</title><subtitle>Musing about computers, technology, and science</subtitle><entry><title type="html">The Frugal Architect Explained</title><link href="https://dovidkopel.com/2023/12/cost-architecture" rel="alternate" type="text/html" title="The Frugal Architect Explained" /><published>2023-12-01T00:00:00+00:00</published><updated>2023-12-01T00:00:00+00:00</updated><id>https://dovidkopel.com/2023/12/cost-architecture</id><content type="html" xml:base="https://dovidkopel.com/2023/12/cost-architecture"><![CDATA[<p>After combing through the words of the brilliant Werner Vogels regarding <a href="https://thefrugalarchitect.com">cost-based architecture</a>, I felt I wanted to elaborate on his concise and precise words.
Here the word <strong>product</strong> is interchangeable for product, service, component, module, application, system, etc.</p>

<h2 id="law-i-make-cost-a-non-functional-requirement"><a href="https://thefrugalarchitect.com/laws/make-cost-a-non-functional-requirement.html">Law I: Make Cost a Non-functional Requirement.</a></h2>
<p>Cost is more than a number. It’s a mantra. Cost savings cannot be an afterthought. It must be designed and accounted for from the beginning. 
The nuance of this first law is that cost is not usually mentioned with requirements. The discussion of cost usually is only after things are design and deployed.
I’ve heard of asking projects of how much will this cost. But I’ve never thought of making cost an actual requirement. In other words, it is not enough to be cost conscious. 
It is needed to go a step further and actually establish how much or little the product in question will cost to operate. 
This means we design around the cost not exceeding this value. Now we will need to factor this against the performance, scalability and resilience that we are expecting for this product.</p>

<h2 id="law-ii-systems-that-last-align-cost-to-business"><a href="https://thefrugalarchitect.com/laws/systems-that-last-align-cost-to-business.html">Law II: Systems that Last Align Cost to Business.</a></h2>
<p>The emphasis here is that there must be a clear and defined relationship between cost and business. That means that as the business grows your costs may grow. That is to be expected and should align properly.
Cost is not expected in all circumstances to be fixed (unless it is). It is usually understood that costs will rise as different dimensions of usage increase.
The word performance is very vague when we are dealing with the specifics of a system. If we are talking about the throughput, even that is too vague. 
The throughput must be discussed within the context of a volume of requests at one time. That means when we are talking about “how long it takes to process a request”, we need to factor in how many requests we are processing at a given time.
The other important factor is how much “stuff” do we have in our data stores that might affect how long things take. 
If our request involves checking against the correlation of other existing transactions the sheer volume of existing transactions will heavily influence the duration of the call.
So too, if we are expecting up to 100 simultaneous calls, or 100,000 simultaneous calls this will greatly affect the request duration. 
All of this is relevant when you are considering cost. In today’s “serverless” world, the ability to <em>infinitely</em> scale without having much or any provisioned resources can take the burden of upfront costs away.
However, depending on what solution you are using for your data storage will deeply affect your ability to scale.</p>

<p>The business model might necessitate a certain SLA for requests. Ideally as your company and business grows the demand on resources and complexity will increase and ideally costs per unit will decrease.
Obviously the overall cost will rise, but as you hit new cost thresholds you will ideally merit volume discounts on computing services.</p>

<p>The engineering cost is another that needs to factored in. As the complexity of a product grows the development costs and maintenance costs will rise. A simple system is cheap to develop.
A complex one can be costly. So sometimes focusing on cutting costs for computing ends up costing a great deal more money for personnel and isn’t worth the expenditure.
In my opinion nothing beats clean simple code. If you can hit your SLAs, don’t be greedy thinking that you will save big with pennies here and there. The sheer cost of engineering and maintenance on a complex system may not be worth it.</p>

<h2 id="law-iii-architecting-is-a-series-of-trade-offs"><a href="https://thefrugalarchitect.com/laws/architecting-is-a-series-of-trade-offs.html">Law III: Architecting is a Series of Trade-offs.</a></h2>
<p>It is well known that there are no perfect systems or solutions. Every system has a balancing act of a myriad of factors. Cost comes in two flavors in the computer world. Cost is money and cost is time.
In reality, they are one because computing costs ends up being all about money. If you are dealing with an algorithm like for compression or machine learning your approach often favors time over quality of the outputted result.
Let’s look at compression its very simple. Today you can have a song that is encoded with a very high quality lossless encoding that is very large in size. Here you are preferring quality over size. 
Or you can have the humble MP3 that is decent quality and notably small in with respect to filesize. When MP3s came out in the early 90’s internet connection speeds were often dial-up and notoriously slow. 
The MP3 was a game changed because the sound quality was good and the file was easily to deliver.</p>

<p>Today, where everyone has a high speed internet connection, we don’t really need MP3s anymore. In architecture, we will make decisions like the MP3 often for well intended reasons. 
Only to soon find out that reason no longer applicable. A new technology comes out, or the nature of the request rate or data schema change in such a way making the architectural choices stale and outdated.
You will always need to choose between several factors when designing a solution, and that rationale may not stand the test of time.
With that said, the cost should adjust with those factors. The trade-offs for using MP3 over a lossless format is the time to transfer and the storage size. It needs to be understood what you are paying for and why.
As times will change and your music streaming service updates, it might charge slightly more to accommodate for the higher operating costs of storing and streaming the lossless files.</p>

<h2 id="law-iv-unobserved-systems-lead-to-unknown-costs"><a href="https://thefrugalarchitect.com/laws/unobserved-systems-lead-to-unknown-costs.html">Law IV: Unobserved Systems Lead to Unknown Costs.</a></h2>
<p>No matter how much planning goes into a system there will always be unforeseen costs. The traffic is higher than expected, the runtime is longer than expected, the file size is larger than expected.
Without visibility into the system it is impossible to be aware of how on target you may or may not be with respect to expected costs. Let us not forget the costs of management and personnel.
Amazon is well known for having the ability to <em>tag</em> almost every resource out there so that you may effectively and easily known your costs. Knowing the costs of resources without their proper context is more or less useless.
If you know your system costs $1,000 last month, and $1,500 the month prior, what is the rationale for that $500 difference is key. Seeing the correlation between your resource and personnel costs against the business is key.
Let’s say that you have metrics that you can see how many incident tickets you have for a given component. Being able to detect that really the lower month of $1,000 was due to downtime because of several critical failures, would greatly inform your cost analysis.
The more you know and the more dots you can connect the more you can nail down waste and over or under utilization.</p>

<h2 id="law-v-cost-aware-architectures-implement-cost-controls"><a href="https://thefrugalarchitect.com/laws/cost-aware-architectures-implement-cost-controls.html">Law V: Cost Aware Architectures Implement Cost Controls.</a></h2>
<p>Beyond merely monitoring components, the ability to easily tune and configure the cost versus <em>power</em> of a given component becomes a surefire way to save money.
Having components separated into tiers of priority is an easy way to isolate what components may be tweaked with over time for cost savings.
A component in a lower priority may be reduced in <em>power</em> when its need is lower. Such that you don’t need 100 nodes to process data if you are only using 2 at the time. 
The question of startup time comes in to play. What if a customer suddenly needs to run a large payload that will overwhelm our pool of nodes. Do we always run 100 nodes to accommodate for those occasions?
You can be sure that AWS thinks about those questions. We all know that AWS Lambda is not actually infinitely scalable, despite us using the term. AWS must spend a lot of money and time coming up with proper projections on how many nodes to dedicate to handle bursts or surges in usage.</p>

<p>The idea that costs and cost-cutting must be justified via business impact is key. Cost-cutting can go too far when you find yourselves without the number of nodes needed to run your request in a given SLA. 
This is a juggling act that must allow for risk. A backup process that runs in a scheduled fashion. Running the process is integral, but running the process hourly versus twice daily may have drastic cost savings that may not be integral to the business needs.</p>

<p>The idea of <em>tuning</em> a product at small levels enables you to tweak parameters easily that may affect costs. Everyone knows a key in good software design is as much as possible parameterize your configuration enabling configuration without requiring a rebuild.
To be able to tune your product in real time, see the effects and persist that configuration is a game changer.
Being able to do that easily without rebuilding a product opens up your application to new modern possibilities.
Especially today where you might be able to use an ML/AI model to attempt to tweak parameters and find a sweet spot where performance and cost are in perfect harmony.</p>

<h2 id="law-vi-cost-optimization-is-incremental"><a href="https://thefrugalarchitect.com/laws/cost-optimization-is-incremental.html">Law VI: Cost Optimization is Incremental.</a></h2>
<p>If you are trying to optimize your costs and doing it properly it doesn’t happen in one day. Even the best designed systems may be improved over time as factors change or expected utilization differs from expected.
This is built on Laws IV and V. You cannot cut costs without proper metrics, and beginning the process of reducing costs starts with tunable or configurable components that you may be able to adjust that affect performance and costs.
Taking property <em>x</em> and turning it from 10 to 1 is not only ill-advised but wrong. The proper way of tweaking parameters is with a dummy environment where you can run controlled tests with varied parameters and evaluate the performance with those new settings.
As mentioned earlier, today there are automated ways of doing this that might find harmony with ML/AI solutions that can help with these adjustments. When tweaking things manually don’t expect to go from spending $1,000 to $50 without breaking things.
You may never be able to get under a certain cost and that may be the reality. Rewrites of certain components might be necessary beyond just tweaking the known configurable options. Breaking out components into smaller bite sized pieces that further determine if this function is run under the given circumstances are all minor ways to reduce milliseconds from task execution.</p>

<h2 id="law-vii-unchallenged-success-leads-to-assumptions"><a href="https://thefrugalarchitect.com/laws/unchallenged-success-leads-to-assumptions.html">Law VII: Unchallenged Success Leads to Assumptions.</a></h2>
<p>Variety is the spice of life. With technology the “tried and true” spirit can lead only too often to complacency and a lack of growth. As Werner concludes the idea of saying we are a “Java shop” is often the cause of a lack of innovation.
Cost optimization, stems from both cutting down and trimming the fat as well as making the core product more powerful and robust with less. 
Let me give an example. Java is notorious for being a technology that is slow on cold starts. That means to get things going to need to wait until more usage where the application is properly loaded, and the system has tuned itself for optimizations.
A recent new feature enables you to warm up the application and save it in that state, so you may be able to restart the application already nice toasty and warm. This dramatically changes the ability to use Java in a serverless capacity.
This now takes a technology that was more or less unusable in serverless ecosystems and would require complete rewrites to take advantage of this new platform called serverless into a reality.
The status quo is the enemy of innovation. The more innovation yields to better performance, and ultimately better cost savings. When you see the lifecycle of R&amp;D to innovation and cost savings that goes back into R&amp;D it’s a beautiful thing.</p>]]></content><author><name>{&quot;login&quot;=&gt;&quot;dovidkopel&quot;, &quot;email&quot;=&gt;&quot;dovid@dovidkopel.com&quot;, &quot;display_name&quot;=&gt;&quot;Dovid Kopel&quot;, &quot;first_name&quot;=&gt;&quot;Dovid&quot;, &quot;last_name&quot;=&gt;&quot;Kopel&quot;}</name><email>dovid@dovidkopel.com</email></author><category term="architecture" /><summary type="html"><![CDATA[After combing through the words of the brilliant Werner Vogels regarding cost-based architecture, I felt I wanted to elaborate on his concise and precise words. Here the word product is interchangeable for product, service, component, module, application, system, etc.]]></summary></entry><entry><title type="html">pg_cron</title><link href="https://dovidkopel.com/2023/11/pg_cron" rel="alternate" type="text/html" title="pg_cron" /><published>2023-11-05T00:00:00+00:00</published><updated>2023-11-05T00:00:00+00:00</updated><id>https://dovidkopel.com/2023/11/pg_cron</id><content type="html" xml:base="https://dovidkopel.com/2023/11/pg_cron"><![CDATA[<p>If you have any large relational databases there is a good chance that you are using materialized views. One way that you can refresh your materialized views is via trigger <code class="language-plaintext highlighter-rouge">on insert</code> or <code class="language-plaintext highlighter-rouge">on uppdate</code> to a table. This can often be too often and cause issues. Until recently when using Spring I would use the <code class="language-plaintext highlighter-rouge">@Scheduled</code> annotation and run a <code class="language-plaintext highlighter-rouge">refresh materialized view</code> directly from the application. This is fine but you may end up with a large number of <code class="language-plaintext highlighter-rouge">@Scheduled</code> methods and that can cause collisions and other unfortunate circumstances. I had always wondered what if I could just schedule a query to be executed on the database itself. It turns out that this exists and is very easy to setup and utilize.</p>

<p>I found <a href="https://aws.amazon.com/blogs/database/schedule-jobs-with-pg_cron-on-your-amazon-rds-for-postgresql-or-amazon-aurora-for-postgresql-databases/">this</a> AWS post that gives you everything you need to get started.
My use case was eliminating certain <code class="language-plaintext highlighter-rouge">refresh materialized view</code> and other queries that did <em>not</em> require any application logic. Simple aggregates or updates that need to run on an ongoing scheduled basis. If you need heavy application or business logic I would avoid using this.
Also keep in mind that the <code class="language-plaintext highlighter-rouge">cron</code> jobs are stored in the <code class="language-plaintext highlighter-rouge">postres</code> database, not your application database. So you will likely use a different use to invoke these commands as the <code class="language-plaintext highlighter-rouge">postgres</code> database should be off limits to an application database user.</p>

<p>This is a great and handy little tool to put on your tool-belt that can cleanup applications and streamline some operations that are long run that normally require a dedicated thread. I’ve found that the <code class="language-plaintext highlighter-rouge">@Scheduled</code> annotation is very quirky if there are multiple jobs scheduled at overlapping intervals. Theoretically you can create a more comprehensive service that will run the scheduled tasks that are at the same time in parallel or in serial. But I found that operations that really don’t require any application logic at all are most appropriate for this use case.</p>

<p>Make sure you that you add the scheduled job that will automatically clear your <code class="language-plaintext highlighter-rouge">jobdetails</code> table for you, otherwise that could cause issues down the road.</p>

<p>Be aware you need to be using PostgreSQL vesrion 12.5 and higher and this is now supported on RDS and Aurora.</p>]]></content><author><name>{&quot;login&quot;=&gt;&quot;dovidkopel&quot;, &quot;email&quot;=&gt;&quot;dovid@dovidkopel.com&quot;, &quot;display_name&quot;=&gt;&quot;Dovid Kopel&quot;, &quot;first_name&quot;=&gt;&quot;Dovid&quot;, &quot;last_name&quot;=&gt;&quot;Kopel&quot;}</name><email>dovid@dovidkopel.com</email></author><category term="aws" /><category term="database" /><category term="postgres" /><category term="scheduling" /><category term="automation" /><category term="java" /><category term="spring-framework" /><summary type="html"><![CDATA[If you have any large relational databases there is a good chance that you are using materialized views. One way that you can refresh your materialized views is via trigger on insert or on uppdate to a table. This can often be too often and cause issues. Until recently when using Spring I would use the @Scheduled annotation and run a refresh materialized view directly from the application. This is fine but you may end up with a large number of @Scheduled methods and that can cause collisions and other unfortunate circumstances. I had always wondered what if I could just schedule a query to be executed on the database itself. It turns out that this exists and is very easy to setup and utilize.]]></summary></entry><entry><title type="html">Amplify</title><link href="https://dovidkopel.com/2023/03/amplify" rel="alternate" type="text/html" title="Amplify" /><published>2023-03-12T00:00:00+00:00</published><updated>2023-03-12T00:00:00+00:00</updated><id>https://dovidkopel.com/2023/03/amplify</id><content type="html" xml:base="https://dovidkopel.com/2023/03/amplify"><![CDATA[<p>If you are looking for an end-to-end solution for a data centric application, Amplify might be for you. Amplify is aimed to be a complete solution from frontend design to authentication and even data. The service is heavily based on the GraphQL and AppSync concept. Let me dig in a bit what this means. With GraphQL you define a model or schema. That schema drives everything else. Amplify will create necessary data storage to support the schema defined, this is in the form of DynamoDB tables. Then their CLI tool will create client-side bindings in JavaScript that give you direct access to CRUD operations on your schema. It is that simple. Until it’s not.</p>

<p>Amplify supports relationships between types in the form of one to one, one to many, and many to many. When adding content in their UI these relationships will determine what data may be selected. All of these tables are each their own Cloud Formation stack behind the scenes. It’s a hell of a mess if you look at it, but Amplify makes it appear simple.</p>

<p>Now what if you want to connect an API or a lambda? Amplify provides a way to integrate that into your model. That way you can use the same simple Javascript that you are using for the data alongside your custom components.</p>

<p>Amplify has two ways of interaction. The first and really the driving force is the CLI. The CLI is its own Javascript client library that enables the user to perform all operations on their amplify application. There is also Amplify Studio which is a frontend website that attempts to let less technical users manage an application. The studio is severely limited in countless ways compared to the CLI, but that is to be expected.</p>

<p>Amplify has two concepts. It’s frontend and it’s backend. The application is actually split into two components that way. For each of those you can have several named environments as means to segregate code and configuration similar to git branches.</p>

<p>One of the major features that Amplify supports, is it’s integration with Figma, the UI wireframe design tool. Amplify let’s you import from Figma wireframes and convert them into usable interfaces that can be linked to your data model without knowing how to write code. For the non-technical user this is a game changer. This enables business users to dictate the requirements through the visual design and directly impact the actual application in a streamlined fashion.</p>

<p>Amplify lacks severely with many things. The build time when working on the schema can be up to 10 minutes or more. Studio doesn’t support half as much as you would expect. So anything beyond a simple application will force you into the CLI. Speaking of the CLI, the environments are confusing and not designed to be enterprise friendly. Environments all live in a single AWS account not allowing for cleaner isolation that you might expect. The connection between git as to what should be included in the git repo is poorly documented. I found it very difficult to handle branches and normal operations.</p>

<p>For a quick prototype with simple data and mostly frontend application Amplify may be a good fit. If you really want business users to drive and be able to easily dictate the frontend, you may love this. Documentation is poor and lots of random errors and failures without rhyme or reason may plague you to stay away. So I recommend keeping your eyes open for future updates at a very promising technology.</p>]]></content><author><name>{&quot;login&quot;=&gt;&quot;dovidkopel&quot;, &quot;email&quot;=&gt;&quot;dovid@dovidkopel.com&quot;, &quot;display_name&quot;=&gt;&quot;Dovid Kopel&quot;, &quot;first_name&quot;=&gt;&quot;Dovid&quot;, &quot;last_name&quot;=&gt;&quot;Kopel&quot;}</name><email>dovid@dovidkopel.com</email></author><category term="aws" /><category term="security" /><category term="authentication" /><category term="rest" /><category term="graphql" /><summary type="html"><![CDATA[If you are looking for an end-to-end solution for a data centric application, Amplify might be for you. Amplify is aimed to be a complete solution from frontend design to authentication and even data. The service is heavily based on the GraphQL and AppSync concept. Let me dig in a bit what this means. With GraphQL you define a model or schema. That schema drives everything else. Amplify will create necessary data storage to support the schema defined, this is in the form of DynamoDB tables. Then their CLI tool will create client-side bindings in JavaScript that give you direct access to CRUD operations on your schema. It is that simple. Until it’s not.]]></summary></entry><entry><title type="html">Privacy &amp;amp; Go</title><link href="https://dovidkopel.com/2022/07/privacy-and-go" rel="alternate" type="text/html" title="Privacy &amp;amp; Go" /><published>2022-07-17T00:00:00+00:00</published><updated>2022-07-17T00:00:00+00:00</updated><id>https://dovidkopel.com/2022/07/privacy-and-go</id><content type="html" xml:base="https://dovidkopel.com/2022/07/privacy-and-go"><![CDATA[<p>I’ve been doing a lot of work recently for a non-profit organization to help my local community deal with private school tuition.
The main reason I became involved was due to a very specific requirement about the system. 
A large number of the potential donors and participants did not want their private and personal financial information to be visible to the administrators and others.
We are not talking about actual PII or “sensitive” information. None of the information here could actually be used to steal or harm our userbase. This is just information like how much they may annually.
The basis of the program is that no family should have to pay more than 20% of their net income towards to tuition. They would pay 1% of their net income and be eligible to have the organization supplement what they pay.
The focus of this article is the design decisions I made and why I made them. For more information about this organization you may visit <a href="https://ahavaschinam.org">https://ahavaschinam.org</a></p>

<p><img src="/images/ACT-AWS.png" alt="Ahavas Chinam Tamid Architecture" /></p>

<h2 id="intro-to-go">Intro to Go</h2>
<p>Let’s start with the main language of choice. I chose to use Go for the backend language. I am the CTO of this organization. No one else was involved in the technology team at the time.
Whenever I am given the opportunity to design a system, the choices I make are extremely deliberate. 
I have been working quite a bit with Go recently and the one thing that screamed out to me is the simplicity in build, distribution, and execution.
As long as you are running the same version of the Go tooling, you are more or less ready to go (no pun intended).</p>

<p>I knew the entire backend was going to be serverless. It was an is essential to me that I am never the sole contributor of a project. At the bare minimum, it is vital that a project be easy to hand off to others.
When there are no other people yet involved you can try to pick very “commonly used” tools and technologies. That is however, not an exact science and totally subject to experience.
Using Python or Javascript may have been the more popular choice, but that does not mean the better choice. Even for novices, I am a stickler for strongly typed languages. 
While Typescript is a greatly improved version of Javascript, I find the maturity of the tooling and libraries in the community are severely lacking. 
As for Python, I love Python, but the build, packaging, and distribution is much more complicated. Versioning is more tedious and simply more work to deal with for a team.</p>

<p>Go is easy. Go is simple. Go is elegant. Go is powerful. Go is good. For what its worth, I’m a recent Go convert. 
Go is now my goto language except for quick scripts and analytics which is most likely Python. Remember that all go builds are native. That means that performance will be as good as native code.
Today we live in a world where many if not all of our code is serverless. We aren’t thinking about memory leaks and code optimization in the exact same way in the past. With that said, Go is fast for development, build, and runtime.
Very often there are trade-offs there. Like an interpreted language which may be quicker to some for development will lack in performance.</p>

<h3 id="go-is-not-oop">Go is not OOP</h3>
<p>One thing I want you be clear about, is that Go is not quite object-oriented in the way that Java or Python users may be familiar with. Go does not support inheritance, rather composition. 
There are no constructors. The <code class="language-plaintext highlighter-rouge">struct</code> is the main player and things are really based on the type of OOP you can accomplish within C. It’s not the end of the world, but your designs will look different from a language that supports inheritance.</p>

<h3 id="error-handling">Error handling</h3>
<p>There are no exceptions and no error “handling” in Go. You have to deal with Tuple style return values. This is also very C influenced. You can wrap errors so that you can deal with typed error handling.</p>

<h3 id="modules--packages">Modules &amp; Packages</h3>
<p>Go is very module centric. Go is very opinionated on how modules are handled and what has access to what. You can only have a single “main.go” which is your application entrypoint.
You must be careful to design your system to handle cyclic imports correctly. This is where interfaces really come into the picture. 
The only way to control package visibility is determined by the case of the first letter of the variable or function. A lowercase entity is only available within a single package.</p>

<h2 id="handling-many-services">Handling many services</h2>
<p>Some people like to take single use to an extreme and end up with a thousand tiny little functions. If that is called microservices…I do mini services.
I make small topic-centric handlers that are self-contained. A REST API will connect to that service. To handle the fact that Go only supports a single <code class="language-plaintext highlighter-rouge">main.go</code> per module I am using a dispatcher.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">package</span> <span class="n">commons</span>

<span class="k">type</span> <span class="n">ApplicationContext</span> <span class="k">struct</span> <span class="p">{</span>
	<span class="n">FunctionName</span> <span class="kt">string</span> <span class="c">//Used to determine which dispatcher is used</span>
	<span class="n">Ctx</span>          <span class="o">*</span><span class="n">lambdacontext</span><span class="o">.</span><span class="n">LambdaContext</span> <span class="c">//Ref to the context of the lambda</span>
	<span class="n">Event</span>        <span class="k">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="n">any</span> <span class="c">//The event payload</span>
	<span class="n">Token</span>        <span class="o">*</span><span class="n">jwt</span><span class="o">.</span><span class="n">Token</span> <span class="c">//Ref. JWT Token if applicable</span>
	<span class="n">Conf</span>         <span class="o">*</span><span class="n">conf</span><span class="o">.</span><span class="n">Conf</span> <span class="c">//Ref. conf instance</span>
	<span class="n">Outputs</span>      <span class="k">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">string</span> <span class="c">//All cloud formation outputs</span>
	<span class="n">Clients</span>      <span class="o">*</span><span class="n">Clients</span> <span class="c">//Reference to all clients </span>
<span class="p">}</span>

<span class="k">type</span> <span class="n">Dispatcher</span> <span class="k">interface</span> <span class="p">{</span>
	<span class="n">Eval</span><span class="p">(</span><span class="n">Context</span> <span class="o">*</span><span class="n">ApplicationContext</span><span class="p">)</span> <span class="kt">bool</span> <span class="c">//Should this dispatcher be used for this call</span>
	<span class="n">Invoke</span><span class="p">(</span><span class="n">Context</span> <span class="o">*</span><span class="n">ApplicationContext</span><span class="p">)</span> <span class="p">(</span><span class="n">any</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="c">//Invoke the dispatcher</span>
	<span class="n">IsHTTPPRoxyRequest</span><span class="p">(</span><span class="n">Context</span> <span class="o">*</span><span class="n">ApplicationContext</span><span class="p">)</span> <span class="kt">bool</span> <span class="c">//Is an HTTP request</span>
	<span class="n">RequiresAuthentication</span><span class="p">(</span><span class="n">Context</span> <span class="o">*</span><span class="n">ApplicationContext</span><span class="p">)</span> <span class="kt">bool</span> <span class="c">//Force auth check</span>
	<span class="n">UsesStripe</span><span class="p">(</span><span class="n">Context</span> <span class="o">*</span><span class="n">ApplicationContext</span><span class="p">)</span> <span class="kt">bool</span> <span class="c">//Instantiate stripe client</span>
	<span class="n">UsesDB</span><span class="p">(</span><span class="n">Context</span> <span class="o">*</span><span class="n">ApplicationContext</span><span class="p">)</span> <span class="kt">bool</span> <span class="c">//Instantiate DB</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This is our <code class="language-plaintext highlighter-rouge">Dispatcher</code> interface and our <code class="language-plaintext highlighter-rouge">ApplicationContext</code>. Our Clients are instances of each client that are used.
Our entire stack is within cloud formation. To make it easy to access stack resources. Here is a nice little function:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">package</span> <span class="n">util</span>

<span class="k">var</span> <span class="n">_outputs</span> <span class="k">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">string</span> <span class="o">=</span> <span class="k">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">string</span><span class="p">{}</span>
<span class="k">var</span> <span class="n">stackNames</span> <span class="o">=</span> <span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">"ACTStack"</span><span class="p">,</span> <span class="s">"ACTApi"</span><span class="p">}</span>

<span class="k">func</span> <span class="n">GetStackOutputs</span><span class="p">()</span> <span class="k">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">string</span> <span class="p">{</span>
	<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">_outputs</span><span class="p">)</span> <span class="o">&gt;</span> <span class="m">0</span> <span class="p">{</span>
		<span class="k">return</span> <span class="n">_outputs</span>
	<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
		<span class="n">cf</span> <span class="o">:=</span> <span class="n">cloudformation</span><span class="o">.</span><span class="n">NewFromConfig</span><span class="p">(</span><span class="n">GetConf</span><span class="p">(</span><span class="no">nil</span><span class="p">))</span>
		<span class="k">for</span> <span class="n">_</span><span class="p">,</span> <span class="n">stack</span> <span class="o">:=</span> <span class="k">range</span> <span class="n">stackNames</span> <span class="p">{</span>
			<span class="n">out</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">cf</span><span class="o">.</span><span class="n">DescribeStacks</span><span class="p">(</span><span class="n">context</span><span class="o">.</span><span class="n">TODO</span><span class="p">(),</span> <span class="o">&amp;</span><span class="n">cloudformation</span><span class="o">.</span><span class="n">DescribeStacksInput</span><span class="p">{</span>
				<span class="n">StackName</span><span class="o">:</span> <span class="n">aws</span><span class="o">.</span><span class="n">String</span><span class="p">(</span><span class="n">stack</span><span class="p">),</span>
			<span class="p">})</span>

			<span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
				<span class="n">log</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span><span class="n">err</span><span class="o">.</span><span class="n">Error</span><span class="p">())</span>
			<span class="p">}</span>

			<span class="n">arn</span> <span class="o">:=</span> <span class="n">regexp</span><span class="o">.</span><span class="n">MustCompile</span><span class="p">(</span><span class="s">"arn:aws:cloudformation:</span><span class="se">\\</span><span class="s">w{2}-</span><span class="se">\\</span><span class="s">w{4}-</span><span class="se">\\</span><span class="s">d:(</span><span class="se">\\</span><span class="s">d{12})"</span><span class="p">)</span>
			<span class="n">_outputs</span><span class="p">[</span><span class="s">"AccountId"</span><span class="p">]</span> <span class="o">=</span> <span class="n">arn</span><span class="o">.</span><span class="n">FindStringSubmatch</span><span class="p">(</span><span class="o">*</span><span class="n">out</span><span class="o">.</span><span class="n">Stacks</span><span class="p">[</span><span class="m">0</span><span class="p">]</span><span class="o">.</span><span class="n">StackId</span><span class="p">)[</span><span class="m">1</span><span class="p">]</span>

			<span class="k">for</span> <span class="n">_</span><span class="p">,</span> <span class="n">o</span> <span class="o">:=</span> <span class="k">range</span> <span class="n">out</span><span class="o">.</span><span class="n">Stacks</span><span class="p">[</span><span class="m">0</span><span class="p">]</span><span class="o">.</span><span class="n">Outputs</span> <span class="p">{</span>
				<span class="n">key</span> <span class="o">:=</span> <span class="o">*</span><span class="n">o</span><span class="o">.</span><span class="n">OutputKey</span>
				<span class="n">key</span> <span class="o">=</span> <span class="n">strings</span><span class="o">.</span><span class="n">Replace</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="s">"Export"</span><span class="p">,</span> <span class="s">""</span><span class="p">,</span> <span class="o">-</span><span class="m">1</span><span class="p">)</span>

				<span class="n">_outputs</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="o">*</span><span class="n">o</span><span class="o">.</span><span class="n">OutputValue</span>
			<span class="p">}</span>			
		<span class="p">}</span>

	<span class="p">}</span>

	<span class="k">return</span> <span class="n">_outputs</span>
<span class="p">}</span>
</code></pre></div></div>

<p>To support dynamic configuration I created simple support for YAML based configuration files. These are generic and environment specific. All you need to do create a <code class="language-plaintext highlighter-rouge">struct</code> that reflects your needs and write the YAML.
There is a popular YAML marshaller that I use then return it. that is the <code class="language-plaintext highlighter-rouge">GetConf()</code> function.</p>

<h3 id="dispatch">Dispatch</h3>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">package</span> <span class="n">main</span> 

<span class="k">func</span> <span class="n">Dispatch</span><span class="p">(</span><span class="n">Context</span> <span class="o">*</span><span class="n">commons</span><span class="o">.</span><span class="n">ApplicationContext</span><span class="p">)</span> <span class="p">(</span><span class="n">any</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">for</span> <span class="n">_</span><span class="p">,</span> <span class="n">dispatcher</span> <span class="o">:=</span> <span class="k">range</span> <span class="n">dispatchers</span> <span class="p">{</span>
		<span class="k">if</span> <span class="n">dispatcher</span><span class="o">.</span><span class="n">Eval</span><span class="p">(</span><span class="n">Context</span><span class="p">)</span> <span class="p">{</span>
			<span class="n">token</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">util</span><span class="o">.</span><span class="n">Authenticate</span><span class="p">(</span><span class="n">dispatcher</span><span class="p">,</span> <span class="n">Context</span><span class="p">)</span>
			<span class="n">Context</span><span class="o">.</span><span class="n">Token</span> <span class="o">=</span> <span class="n">token</span>

			<span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
				<span class="k">return</span> <span class="n">events</span><span class="o">.</span><span class="n">APIGatewayProxyResponse</span><span class="p">{</span><span class="n">StatusCode</span><span class="o">:</span> <span class="m">401</span><span class="p">},</span> <span class="no">nil</span>
			<span class="p">}</span>

			<span class="n">test</span><span class="o">.</span><span class="n">GetClients</span><span class="p">(</span><span class="n">Context</span><span class="p">,</span> <span class="n">dispatcher</span><span class="p">)</span>
			<span class="n">output</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">dispatcher</span><span class="o">.</span><span class="n">Invoke</span><span class="p">(</span><span class="n">Context</span><span class="p">)</span>

			<span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
				<span class="n">log</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span><span class="n">err</span><span class="p">)</span>
				<span class="n">statusCode</span> <span class="o">:=</span> <span class="m">500</span>

				<span class="k">if</span> <span class="n">errors</span><span class="o">.</span><span class="n">Is</span><span class="p">(</span><span class="n">err</span><span class="p">,</span> <span class="n">commons</span><span class="o">.</span><span class="n">ForbiddenError</span><span class="p">)</span> <span class="p">{</span>
					<span class="n">statusCode</span> <span class="o">=</span> <span class="m">403</span>
				<span class="p">}</span>

				<span class="k">return</span> <span class="n">events</span><span class="o">.</span><span class="n">APIGatewayProxyResponse</span><span class="p">{</span>
					<span class="n">StatusCode</span><span class="o">:</span> <span class="n">statusCode</span><span class="p">,</span>
					<span class="n">Headers</span><span class="o">:</span>    <span class="n">GetCorsHeaders</span><span class="p">(</span><span class="n">Context</span><span class="p">),</span>
					<span class="n">Body</span><span class="o">:</span>       <span class="n">err</span><span class="o">.</span><span class="n">Error</span><span class="p">(),</span>
				<span class="p">},</span> <span class="no">nil</span>
			<span class="p">}</span>

			<span class="k">return</span> <span class="n">ProcessHTTPRequest</span><span class="p">(</span><span class="n">dispatcher</span><span class="p">,</span> <span class="n">Context</span><span class="p">,</span> <span class="n">output</span><span class="p">)</span>
		<span class="p">}</span>
	<span class="p">}</span>
	<span class="k">return</span> <span class="k">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="n">any</span><span class="p">{},</span> <span class="no">nil</span>
<span class="p">}</span>
</code></pre></div></div>

<p>We have an array of <code class="language-plaintext highlighter-rouge">dispatchers</code> one per module. The <code class="language-plaintext highlighter-rouge">Eval()</code> function determines if this is the appropriate dispatcher for the current invocation. The <code class="language-plaintext highlighter-rouge">Authenticate</code> will populate a <code class="language-plaintext highlighter-rouge">jwt.Token</code> as applicable and will enforce if specified.
If you look at line 10. That handles a scenario where authentication is required and fails. Line 20-21 is made for scenarios where depending on the output of the call a 403 would be returned.
This is an example of unwrapping errors and evaluating the error type.</p>

<h2 id="privacy">Privacy</h2>
<p>The second part of this article is how privacy first is approached. The basis of the system design is that the data is in three different systems that are actually naturally that way. I’m not really going out of my way to partition the data.
The general goal is through data isolation and segmentation as well as encryption you can make it very difficult for even a highly privileged user to obtain this private information. 
Remember, we try to focus on preventing the plausible and likely, and we also try to deter the user and make it very difficult to access that data. So wherever data is isolated it should require at least access to two data stores for the data to have any meaning. 
The data by itself without the secondary data store is completely useless.</p>

<h3 id="cognito">Cognito</h3>
<p>The system begins with AWS Cognito. Using Cognito for user management is generally a pleasure and simple. We are utilizing the groups to track what group users are in. I am heavily enriching the JWT Token with data prior to the token being generated.
Now the user in Cognito is identified with a <code class="language-plaintext highlighter-rouge">sub</code> id which is a GUUID. Our other data storage is our relational database PostgreSQL which utilizes the user’s id</p>

<h3 id="postgresql">PostgreSQL</h3>
<p>Without going into specifics for our application, the main takeway is all users utilize the id created in Cognito. So in my relational database I don’t actually have any user profile information (first name, last name, etc..). 
I do have much more complex data for the application. The private data is actually stored in PostgreSQL but it is encrypted using KMS. This encrypted data is only able to be decrypted by specific lambda functions that have access to the KMS key.
Since the PostgreSQL data actually cannot be identified alone it creates another layer of security and isolation for that private information. Not that this is really needed, but it is how things best fit and was an added bonus.</p>

<h3 id="stripe">Stripe</h3>
<p>We are using stripe for payment processing. If we can easily look at stripe and figure out how much the payment are…that will remove the anonymity that we are striving for. It turns out that Stripe’s “Customer” does not require <em>any</em> information when created.
Therefore, I can create a customer, attach a credit card, and make a payment without having any user information on Stripe. This means that we can have another layer of data isolation. The only way to connect that information for the user would be with the stripe customer id.
We store the stripe customer id in PostgreSQL, but it is encrypted. We also store a one-way-hash for quick lookups for events.</p>

<h3 id="ocr">OCR</h3>
<p>Part of this system we have the user upload some tax forms. They are processed and data extracted. A small secret sauce is how I can do this without worrying about the social security numbers that are on these documents. 
Always remember that even if you don’t want to keep the sensitive data, if it runs through your system you are responsible for that data. Make sure you know what you are doing!</p>

<h2 id="conclusion">Conclusion</h2>
<p>I want to summarize that the approaches I am using is how to handle sensitive data as well. But you better know what you are doing first. Here we are only talking about non-sensitive, but we are treating it like a hot potato.
At no point are we letting privacy sacrifice the integrity of the application. I will say that with a very large database, some of these approaches will affect performance and should be dealt with on a case by case scenario.</p>]]></content><author><name>{&quot;login&quot;=&gt;&quot;dovidkopel&quot;, &quot;email&quot;=&gt;&quot;dovid@dovidkopel.com&quot;, &quot;display_name&quot;=&gt;&quot;Dovid Kopel&quot;, &quot;first_name&quot;=&gt;&quot;Dovid&quot;, &quot;last_name&quot;=&gt;&quot;Kopel&quot;}</name><email>dovid@dovidkopel.com</email></author><category term="aws" /><category term="authentication" /><category term="security" /><category term="privacy" /><category term="jwt" /><category term="go" /><summary type="html"><![CDATA[I’ve been doing a lot of work recently for a non-profit organization to help my local community deal with private school tuition. The main reason I became involved was due to a very specific requirement about the system. A large number of the potential donors and participants did not want their private and personal financial information to be visible to the administrators and others. We are not talking about actual PII or “sensitive” information. None of the information here could actually be used to steal or harm our userbase. This is just information like how much they may annually. The basis of the program is that no family should have to pay more than 20% of their net income towards to tuition. They would pay 1% of their net income and be eligible to have the organization supplement what they pay. The focus of this article is the design decisions I made and why I made them. For more information about this organization you may visit https://ahavaschinam.org]]></summary></entry><entry><title type="html">AWS Cognito &amp;amp; JWT</title><link href="https://dovidkopel.com/2020/04/aws-cognito-jwt" rel="alternate" type="text/html" title="AWS Cognito &amp;amp; JWT" /><published>2020-04-05T00:00:00+00:00</published><updated>2020-04-05T00:00:00+00:00</updated><id>https://dovidkopel.com/2020/04/aws-cognito-jwt</id><content type="html" xml:base="https://dovidkopel.com/2020/04/aws-cognito-jwt"><![CDATA[<p>Recently I had to design and implement a solution that used a third-party user management system for authentication. 
I decided to use <a href="/cloud-vendor/aws/services/cognito">Amazon’s Cognito</a> service, more specifically the User Pool aspect. 
The third-party service was able to work with SAML, and so does Cognito.
Cognito’s output that you use is a <a href="https://jwt.io">JWT</a> object. 
The backend system is written using Java 8 and Spring Framework and Spring Security.</p>

<p>Using Spring Boot parent POM:</p>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;parent&gt;</span>
    <span class="nt">&lt;groupId&gt;</span>org.springframework.boot<span class="nt">&lt;/groupId&gt;</span>
    <span class="nt">&lt;artifactId&gt;</span>spring-boot-starter-parent<span class="nt">&lt;/artifactId&gt;</span>
    <span class="nt">&lt;version&gt;</span>2.1.5.RELEASE<span class="nt">&lt;/version&gt;</span>
    <span class="nt">&lt;relativePath/&gt;</span>
<span class="nt">&lt;/parent&gt;</span>
</code></pre></div></div>

<p>I have a great deal of experience building systems using Spring Security because of its extremely adaptable security model.
Initially I had attempted to use the Auth0 library as they had modules that were ready for Spring Security. 
For several reasons I need to make modifications to those libraries and they were designed in a way that made it impossible to simply extend those libraries.
I ended up taking some of that code and just copying it and pasting it into my base classes and work from there.</p>

<p>The two dependencies I am using for managing JWT objects is:</p>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;dependencies&gt;</span>
    <span class="nt">&lt;dependency&gt;</span>
        <span class="nt">&lt;groupId&gt;</span>com.auth0<span class="nt">&lt;/groupId&gt;</span>
        <span class="nt">&lt;artifactId&gt;</span>java-jwt<span class="nt">&lt;/artifactId&gt;</span>
    <span class="nt">&lt;/dependency&gt;</span>
    <span class="nt">&lt;dependency&gt;</span>
        <span class="nt">&lt;groupId&gt;</span>com.auth0<span class="nt">&lt;/groupId&gt;</span>
        <span class="nt">&lt;artifactId&gt;</span>jwks-rsa<span class="nt">&lt;/artifactId&gt;</span>
    <span class="nt">&lt;/dependency&gt;</span>
<span class="nt">&lt;/dependencies&gt;</span>
</code></pre></div></div>

<p>If you are interested you can probably use:</p>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;dependency&gt;</span>
    <span class="nt">&lt;groupId&gt;</span>com.auth0<span class="nt">&lt;/groupId&gt;</span>
    <span class="nt">&lt;artifactId&gt;</span>auth0-spring-security-api<span class="nt">&lt;/artifactId&gt;</span>
    <span class="nt">&lt;version&gt;</span>1.3.0<span class="nt">&lt;/version&gt;</span>
<span class="nt">&lt;/dependency&gt;</span>
</code></pre></div></div>

<p>There are several things I want to mention with my security model that required a lot of tweaks:</p>
<ol>
  <li>We are using the user groups that are passed along in the JWT object in <code class="language-plaintext highlighter-rouge">cognito:groups</code> key.</li>
  <li>Needed to support a custom “granting” system that allows certain calls to “grant” itself certain roles or permissions for the duration of the call without requiring the user to possess those roles/permissions.</li>
  <li>Needed to support service tokens, external services that access the API and will not authenticate by means of a JWT. The list of authorities for each service would be pre-defined.</li>
</ol>

<p>«««&lt; HEAD</p>
<h2 id="support-for-multiple-jwt-authorization-sources">Support for multiple JWT authorization sources</h2>
<p>=======</p>
<h1 id="support-for-multiple-jwt-authorization-sources-1">Support for multiple JWT authorization sources</h1>
<blockquote>
  <blockquote>
    <blockquote>
      <blockquote>
        <blockquote>
          <blockquote>
            <blockquote>
              <p>staging</p>
            </blockquote>
          </blockquote>
        </blockquote>
      </blockquote>
    </blockquote>
  </blockquote>
</blockquote>

<p>Part of what makes Spring Security such a great system is that almost everything can be configured and tweaked, and at the same time like all Spring libraries they are sensible defaults.
An <code class="language-plaintext highlighter-rouge">AuthenticationProvider</code> is an interface that is very generic and at its core the interface used to actually either authenticate or reject a support <code class="language-plaintext highlighter-rouge">Authenatication</code>.
There are many layers built-in to Spring Security for common patterns and needs such as the <code class="language-plaintext highlighter-rouge">UserDetailsService</code>. 
Spring Security supports at the same time multiple <code class="language-plaintext highlighter-rouge">AuthenticationProvider</code>s but for multiple custom <code class="language-plaintext highlighter-rouge">AuthenticationProvider</code> you will need to use an <code class="language-plaintext highlighter-rouge">AuthenticationManager</code>.
For testing purposes I wanted to allow the use of real user credentials from the third-party service as well as credentials that are generated dynamically for the various use-cases as needed.
The first that you need to figure out is how to create your own JWT local keystore. 
That means that you should be able to cryptographically create the token prior to a test and then be able to have the backend verify it and use it correctly.
With limited time and resources if I am writing tests for the front-end they are generally going to be end-to-end tests, not unit tests.
That is why I wanted to use real tokens and make sure that the correct roles work at the right times and the opposite as well.</p>

<p>I created my own version of <code class="language-plaintext highlighter-rouge">JwtAuthenticationProvider</code> that takes in a <code class="language-plaintext highlighter-rouge">Set&lt;JwtAuthorizer</code>. I made up that class but it is the constructor parameters that the <code class="language-plaintext highlighter-rouge">JwtAuthenticationProvider</code> uses.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">JwtAuthorizer</span> <span class="o">{</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="nc">JwkProvider</span> <span class="n">jwkProvider</span><span class="o">;</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="kt">byte</span><span class="o">[]</span> <span class="n">secret</span><span class="o">;</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="nc">String</span> <span class="n">issuer</span><span class="o">;</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="nc">String</span> <span class="n">audience</span><span class="o">;</span>

    <span class="kd">public</span> <span class="nf">JwtAuthorizer</span><span class="o">(</span><span class="nc">JwkProvider</span> <span class="n">jwkProvider</span><span class="o">,</span> <span class="nc">String</span> <span class="n">issuer</span><span class="o">,</span> <span class="nc">String</span> <span class="n">audience</span><span class="o">,</span> <span class="kt">byte</span><span class="o">[]</span> <span class="n">secret</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">this</span><span class="o">.</span><span class="na">jwkProvider</span> <span class="o">=</span> <span class="n">jwkProvider</span><span class="o">;</span>
        <span class="k">this</span><span class="o">.</span><span class="na">issuer</span> <span class="o">=</span> <span class="n">issuer</span><span class="o">;</span>
        <span class="k">this</span><span class="o">.</span><span class="na">audience</span> <span class="o">=</span> <span class="n">audience</span><span class="o">;</span>
        <span class="k">this</span><span class="o">.</span><span class="na">secret</span> <span class="o">=</span> <span class="n">secret</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="nf">JwtAuthorizer</span><span class="o">(</span><span class="nc">JwkProvider</span> <span class="n">jwkProvider</span><span class="o">,</span> <span class="nc">String</span> <span class="n">issuer</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">this</span><span class="o">.</span><span class="na">jwkProvider</span> <span class="o">=</span> <span class="n">jwkProvider</span><span class="o">;</span>
        <span class="k">this</span><span class="o">.</span><span class="na">issuer</span> <span class="o">=</span> <span class="n">issuer</span><span class="o">;</span>
        <span class="k">this</span><span class="o">.</span><span class="na">audience</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
        <span class="k">this</span><span class="o">.</span><span class="na">secret</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="nc">JwkProvider</span> <span class="nf">getJwkProvider</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">jwkProvider</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="nc">String</span> <span class="nf">getIssuer</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">issuer</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="nc">String</span> <span class="nf">getAudience</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">audience</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="kt">byte</span><span class="o">[]</span> <span class="nf">getSecret</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">secret</span><span class="o">;</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Here is my slightly modified version of the <code class="language-plaintext highlighter-rouge">JwtAuthenticationProvider</code>. The original source is available <a href="https://github.com/auth0/auth0-spring-security-api/blob/master/lib/src/main/java/com/auth0/spring/security/api/JwtAuthenticationProvider.java">here</a>.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">JwtAuthenticationProvider</span> <span class="kd">implements</span> <span class="nc">AuthenticationProvider</span> <span class="o">{</span>

    <span class="kd">private</span> <span class="kd">static</span> <span class="nc">Logger</span> <span class="n">logger</span> <span class="o">=</span> <span class="nc">LoggerFactory</span><span class="o">.</span><span class="na">getLogger</span><span class="o">(</span><span class="nc">JwtAuthenticationProvider</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>

    <span class="kd">private</span> <span class="kd">final</span> <span class="nc">Set</span><span class="o">&lt;</span><span class="nc">JwtAuthorizer</span><span class="o">&gt;</span> <span class="n">authorizers</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HashSet</span><span class="o">();</span>

    <span class="kd">private</span> <span class="kt">long</span> <span class="n">leeway</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>

    <span class="kd">public</span> <span class="nf">JwtAuthenticationProvider</span><span class="o">(</span><span class="nc">Set</span><span class="o">&lt;</span><span class="nc">JwtAuthorizer</span><span class="o">&gt;</span> <span class="n">authorizers</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">this</span><span class="o">.</span><span class="na">authorizers</span><span class="o">.</span><span class="na">addAll</span><span class="o">(</span><span class="n">authorizers</span><span class="o">);</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="nf">JwtAuthenticationProvider</span><span class="o">(</span><span class="nc">JwkProvider</span> <span class="n">jwkProvider</span><span class="o">,</span> <span class="nc">String</span> <span class="n">issuer</span><span class="o">,</span> <span class="nc">String</span> <span class="n">audience</span><span class="o">,</span> <span class="kt">byte</span><span class="o">[]</span> <span class="n">secret</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">this</span><span class="o">.</span><span class="na">authorizers</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="k">new</span> <span class="nc">JwtAuthorizer</span><span class="o">(</span><span class="n">jwkProvider</span><span class="o">,</span> <span class="n">issuer</span><span class="o">,</span> <span class="n">audience</span><span class="o">,</span> <span class="n">secret</span><span class="o">));</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="nf">JwtAuthenticationProvider</span><span class="o">(</span><span class="nc">JwkProvider</span> <span class="n">jwkProvider</span><span class="o">,</span> <span class="nc">String</span> <span class="n">issuer</span><span class="o">,</span> <span class="nc">String</span> <span class="n">audience</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">this</span><span class="o">.</span><span class="na">authorizers</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="k">new</span> <span class="nc">JwtAuthorizer</span><span class="o">(</span><span class="n">jwkProvider</span><span class="o">,</span> <span class="n">issuer</span><span class="o">,</span> <span class="n">audience</span><span class="o">,</span> <span class="kc">null</span><span class="o">));</span>
    <span class="o">}</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">supports</span><span class="o">(</span><span class="nc">Class</span><span class="o">&lt;?&gt;</span> <span class="n">authentication</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="nc">JwtAuthentication</span><span class="o">.</span><span class="na">class</span><span class="o">.</span><span class="na">isAssignableFrom</span><span class="o">(</span><span class="n">authentication</span><span class="o">);</span>
    <span class="o">}</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">Authentication</span> <span class="nf">authenticate</span><span class="o">(</span><span class="nc">Authentication</span> <span class="n">authentication</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">AuthenticationException</span> <span class="o">{</span>
        <span class="k">if</span> <span class="o">(!</span><span class="n">supports</span><span class="o">(</span><span class="n">authentication</span><span class="o">.</span><span class="na">getClass</span><span class="o">()))</span> <span class="o">{</span>
            <span class="k">return</span> <span class="kc">null</span><span class="o">;</span>
        <span class="o">}</span>

        <span class="nc">JwtAuthentication</span> <span class="n">jwt</span> <span class="o">=</span> <span class="o">(</span><span class="nc">JwtAuthentication</span><span class="o">)</span> <span class="n">authentication</span><span class="o">;</span>
        <span class="k">for</span><span class="o">(</span><span class="nc">JwtAuthorizer</span> <span class="n">authorizer</span> <span class="o">:</span> <span class="n">authorizers</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">try</span> <span class="o">{</span>
                <span class="kd">final</span> <span class="nc">Authentication</span> <span class="n">jwtAuth</span> <span class="o">=</span> <span class="n">jwt</span><span class="o">.</span><span class="na">verify</span><span class="o">(</span><span class="n">jwtVerifier</span><span class="o">(</span><span class="n">jwt</span><span class="o">));</span>
                <span class="n">logger</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Authenticated with jwt with scopes {}"</span><span class="o">,</span> <span class="n">jwtAuth</span><span class="o">.</span><span class="na">getAuthorities</span><span class="o">());</span>
                <span class="k">return</span> <span class="n">jwtAuth</span><span class="o">;</span>
            <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">Exception</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
                <span class="c1">// Not needed, just to catch.</span>
                <span class="n">logger</span><span class="o">.</span><span class="na">warn</span><span class="o">(</span><span class="s">"An authentication exception was thrown: {}"</span><span class="o">,</span> <span class="n">e</span><span class="o">.</span><span class="na">getMessage</span><span class="o">());</span>
            <span class="o">}</span>
        <span class="o">}</span>

        <span class="k">throw</span> <span class="k">new</span> <span class="nf">BadCredentialsException</span><span class="o">(</span><span class="s">"Not a valid token"</span><span class="o">);</span>
    <span class="o">}</span>

    <span class="cm">/**
     * Allow a leeway to use on the JWT verification.
     *
     * @param leeway the leeway value to use expressed in seconds.
     * @return this same provider instance to chain calls.
     */</span>
    <span class="nd">@SuppressWarnings</span><span class="o">(</span><span class="s">"unused"</span><span class="o">)</span>
    <span class="kd">public</span> <span class="nc">JwtAuthenticationProvider</span> <span class="nf">withJwtVerifierLeeway</span><span class="o">(</span><span class="kt">long</span> <span class="n">leeway</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">this</span><span class="o">.</span><span class="na">leeway</span> <span class="o">=</span> <span class="n">leeway</span><span class="o">;</span>
        <span class="k">return</span> <span class="k">this</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kd">private</span> <span class="nc">JWTVerifier</span> <span class="nf">jwtVerifier</span><span class="o">(</span><span class="nc">JwtAuthentication</span> <span class="n">authentication</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">AuthenticationException</span> <span class="o">{</span>
        <span class="k">if</span> <span class="o">(</span><span class="n">secret</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">return</span> <span class="nf">providerForHS256</span><span class="o">(</span><span class="n">secret</span><span class="o">,</span> <span class="n">issuer</span><span class="o">,</span> <span class="n">audience</span><span class="o">,</span> <span class="n">leeway</span><span class="o">);</span>
        <span class="o">}</span>
        <span class="kd">final</span> <span class="nc">String</span> <span class="n">kid</span> <span class="o">=</span> <span class="n">authentication</span><span class="o">.</span><span class="na">getKeyId</span><span class="o">();</span>
        <span class="k">if</span> <span class="o">(</span><span class="n">kid</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">throw</span> <span class="k">new</span> <span class="nf">BadCredentialsException</span><span class="o">(</span><span class="s">"No kid found in jwt"</span><span class="o">);</span>
        <span class="o">}</span>
        <span class="k">if</span> <span class="o">(</span><span class="n">jwkProvider</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">throw</span> <span class="k">new</span> <span class="nf">AuthenticationServiceException</span><span class="o">(</span><span class="s">"Missing jwk provider"</span><span class="o">);</span>
        <span class="o">}</span>
        <span class="k">try</span> <span class="o">{</span>
            <span class="kd">final</span> <span class="nc">Jwk</span> <span class="n">jwk</span> <span class="o">=</span> <span class="n">jwkProvider</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">kid</span><span class="o">);</span>
            <span class="k">return</span> <span class="nf">providerForRS256</span><span class="o">((</span><span class="nc">RSAPublicKey</span><span class="o">)</span> <span class="n">jwk</span><span class="o">.</span><span class="na">getPublicKey</span><span class="o">(),</span> <span class="n">issuer</span><span class="o">,</span> <span class="n">audience</span><span class="o">,</span> <span class="n">leeway</span><span class="o">);</span>
        <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">SigningKeyNotFoundException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">throw</span> <span class="k">new</span> <span class="nf">AuthenticationServiceException</span><span class="o">(</span><span class="s">"Could not retrieve jwks from issuer"</span><span class="o">,</span> <span class="n">e</span><span class="o">);</span>
        <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">InvalidPublicKeyException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">throw</span> <span class="k">new</span> <span class="nf">AuthenticationServiceException</span><span class="o">(</span><span class="s">"Could not retrieve public key from issuer"</span><span class="o">,</span> <span class="n">e</span><span class="o">);</span>
        <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">JwkException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">throw</span> <span class="k">new</span> <span class="nf">AuthenticationServiceException</span><span class="o">(</span><span class="s">"Cannot authenticate with jwt"</span><span class="o">,</span> <span class="n">e</span><span class="o">);</span>
        <span class="o">}</span>
    <span class="o">}</span>

    <span class="kd">private</span> <span class="kd">static</span> <span class="nc">JWTVerifier</span> <span class="nf">providerForRS256</span><span class="o">(</span><span class="nc">RSAPublicKey</span> <span class="n">publicKey</span><span class="o">,</span> <span class="nc">String</span> <span class="n">issuer</span><span class="o">,</span> <span class="nc">String</span> <span class="n">audience</span><span class="o">,</span> <span class="kt">long</span> <span class="n">leeway</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="no">JWT</span><span class="o">.</span><span class="na">require</span><span class="o">(</span><span class="nc">Algorithm</span><span class="o">.</span><span class="na">RSA256</span><span class="o">(</span><span class="n">publicKey</span><span class="o">,</span> <span class="kc">null</span><span class="o">))</span>
                <span class="o">.</span><span class="na">withIssuer</span><span class="o">(</span><span class="n">issuer</span><span class="o">)</span>
                <span class="o">.</span><span class="na">withAudience</span><span class="o">(</span><span class="n">audience</span><span class="o">)</span>
                <span class="o">.</span><span class="na">acceptLeeway</span><span class="o">(</span><span class="n">leeway</span><span class="o">)</span>
                <span class="o">.</span><span class="na">build</span><span class="o">();</span>
    <span class="o">}</span>

    <span class="kd">private</span> <span class="kd">static</span> <span class="nc">JWTVerifier</span> <span class="nf">providerForHS256</span><span class="o">(</span><span class="kt">byte</span><span class="o">[]</span> <span class="n">secret</span><span class="o">,</span> <span class="nc">String</span> <span class="n">issuer</span><span class="o">,</span> <span class="nc">String</span> <span class="n">audience</span><span class="o">,</span> <span class="kt">long</span> <span class="n">leeway</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="no">JWT</span><span class="o">.</span><span class="na">require</span><span class="o">(</span><span class="nc">Algorithm</span><span class="o">.</span><span class="na">HMAC256</span><span class="o">(</span><span class="n">secret</span><span class="o">))</span>
                <span class="o">.</span><span class="na">withIssuer</span><span class="o">(</span><span class="n">issuer</span><span class="o">)</span>
                <span class="o">.</span><span class="na">withAudience</span><span class="o">(</span><span class="n">audience</span><span class="o">)</span>
                <span class="o">.</span><span class="na">acceptLeeway</span><span class="o">(</span><span class="n">leeway</span><span class="o">)</span>
                <span class="o">.</span><span class="na">build</span><span class="o">();</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>The only real change I’ve made here was iterating through the configured list of <code class="language-plaintext highlighter-rouge">JwtAuthorizer</code>s.
There is an alternative approach that I could have taken for this implementation.
Spring Security uses the <code class="language-plaintext highlighter-rouge">boolean supports(Class&lt;?&gt; authentication)</code> method to determine if the <code class="language-plaintext highlighter-rouge">AuthenticationProvider</code> is appropriate for the <code class="language-plaintext highlighter-rouge">Authentication</code> supplied.
Unfortunately it doesn’t allow for a mechanism to indicate that the provider is the right type but the wrong authorizer.
Alternatively, you might be able to check if the <code class="language-plaintext highlighter-rouge">Authentication</code> object is an instance of <code class="language-plaintext highlighter-rouge">JwtAuthentication</code> and that it’s <code class="language-plaintext highlighter-rouge">kid</code> matches the authorizer’s.
I prefer to use the <code class="language-plaintext highlighter-rouge">supports</code> method for determining the type match, not getting into the more nitty-gritty of the which authorizer.
I like the idea of only having a single <code class="language-plaintext highlighter-rouge">JwtAuthenticationProvider</code> and making the <code class="language-plaintext highlighter-rouge">JwtAuthorizer</code> programmatic.
This would allow for runtime configuration and as many authorizer instances as desired.</p>

<p>Now we need to configure support for our locally served <code class="language-plaintext highlighter-rouge">jwks.json</code> file. 
My system configuration uses docker and since the backend is setup first and then then the nginx to host the front-end.
I needed to make sure that I could run tests if I wanted to using JWT that didn’t depend on the front-end being up, especially in an environment like CodeBuild.
I decided to store the <code class="language-plaintext highlighter-rouge">jwks.json</code> as a classpath resource. This is a very simple class that implements the <code class="language-plaintext highlighter-rouge">JwkProvider</code> interface.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">LocalJwkProvider</span> <span class="kd">implements</span> <span class="nc">JwkProvider</span> <span class="o">{</span>
	<span class="kd">private</span> <span class="nc">InputStream</span> <span class="n">input</span><span class="o">;</span>
	<span class="kd">private</span> <span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Object</span><span class="o">&gt;</span> <span class="n">keys</span><span class="o">;</span>

	<span class="kd">public</span> <span class="nf">LocalJwkProvider</span><span class="o">(</span><span class="nc">InputStream</span> <span class="n">input</span><span class="o">)</span> <span class="o">{</span>
		<span class="k">this</span><span class="o">.</span><span class="na">input</span> <span class="o">=</span> <span class="n">input</span><span class="o">;</span>
		<span class="k">try</span> <span class="o">{</span>
			<span class="k">this</span><span class="o">.</span><span class="na">keys</span> <span class="o">=</span> <span class="n">getJwks</span><span class="o">();</span>
		<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">Exception</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>

		<span class="o">}</span>
	<span class="o">}</span>

	<span class="kd">private</span> <span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Object</span><span class="o">&gt;</span> <span class="nf">getJwks</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">SigningKeyNotFoundException</span> <span class="o">{</span>
		<span class="k">try</span> <span class="o">{</span>
			<span class="kd">final</span> <span class="nc">JsonFactory</span> <span class="n">factory</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">JsonFactory</span><span class="o">();</span>
			<span class="kd">final</span> <span class="nc">JsonParser</span> <span class="n">parser</span> <span class="o">=</span> <span class="n">factory</span><span class="o">.</span><span class="na">createParser</span><span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">input</span><span class="o">);</span>
			<span class="kd">final</span> <span class="nc">TypeReference</span><span class="o">&lt;</span><span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Object</span><span class="o">&gt;&gt;</span> <span class="n">typeReference</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TypeReference</span><span class="o">&lt;</span><span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Object</span><span class="o">&gt;&gt;()</span> <span class="o">{};</span>
			<span class="k">return</span> <span class="k">new</span> <span class="nf">ObjectMapper</span><span class="o">().</span><span class="na">reader</span><span class="o">().</span><span class="na">readValue</span><span class="o">(</span><span class="n">parser</span><span class="o">,</span> <span class="n">typeReference</span><span class="o">);</span>
		<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
			<span class="k">throw</span> <span class="k">new</span> <span class="nf">SigningKeyNotFoundException</span><span class="o">(</span><span class="s">"Problem with parsing..."</span><span class="o">,</span> <span class="n">e</span><span class="o">);</span>
		<span class="o">}</span>
	<span class="o">}</span>

	<span class="kd">static</span> <span class="nc">Jwk</span> <span class="nf">fromValues</span><span class="o">(</span><span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Object</span><span class="o">&gt;</span> <span class="n">map</span><span class="o">)</span> <span class="o">{</span>
		<span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Object</span><span class="o">&gt;</span> <span class="n">values</span> <span class="o">=</span> <span class="nc">Maps</span><span class="o">.</span><span class="na">newHashMap</span><span class="o">(</span><span class="n">map</span><span class="o">);</span>
		<span class="nc">String</span> <span class="n">kid</span> <span class="o">=</span> <span class="o">(</span><span class="nc">String</span><span class="o">)</span> <span class="n">values</span><span class="o">.</span><span class="na">remove</span><span class="o">(</span><span class="s">"kid"</span><span class="o">);</span>
		<span class="nc">String</span> <span class="n">kty</span> <span class="o">=</span> <span class="o">(</span><span class="nc">String</span><span class="o">)</span> <span class="n">values</span><span class="o">.</span><span class="na">remove</span><span class="o">(</span><span class="s">"kty"</span><span class="o">);</span>
		<span class="nc">String</span> <span class="n">alg</span> <span class="o">=</span> <span class="o">(</span><span class="nc">String</span><span class="o">)</span> <span class="n">values</span><span class="o">.</span><span class="na">remove</span><span class="o">(</span><span class="s">"alg"</span><span class="o">);</span>
		<span class="nc">String</span> <span class="n">use</span> <span class="o">=</span> <span class="o">(</span><span class="nc">String</span><span class="o">)</span> <span class="n">values</span><span class="o">.</span><span class="na">remove</span><span class="o">(</span><span class="s">"use"</span><span class="o">);</span>
		<span class="nc">Object</span> <span class="n">keyOps</span> <span class="o">=</span> <span class="n">values</span><span class="o">.</span><span class="na">remove</span><span class="o">(</span><span class="s">"key_ops"</span><span class="o">);</span>
		<span class="nc">String</span> <span class="n">x5u</span> <span class="o">=</span> <span class="o">(</span><span class="nc">String</span><span class="o">)</span> <span class="n">values</span><span class="o">.</span><span class="na">remove</span><span class="o">(</span><span class="s">"x5u"</span><span class="o">);</span>
		<span class="nc">List</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="n">x5c</span> <span class="o">=</span> <span class="o">(</span><span class="nc">List</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;)</span> <span class="n">values</span><span class="o">.</span><span class="na">remove</span><span class="o">(</span><span class="s">"x5c"</span><span class="o">);</span>
		<span class="nc">String</span> <span class="n">x5t</span> <span class="o">=</span> <span class="o">(</span><span class="nc">String</span><span class="o">)</span> <span class="n">values</span><span class="o">.</span><span class="na">remove</span><span class="o">(</span><span class="s">"x5t"</span><span class="o">);</span>
		<span class="k">if</span> <span class="o">(</span><span class="n">kty</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
			<span class="k">throw</span> <span class="k">new</span> <span class="nf">IllegalArgumentException</span><span class="o">(</span><span class="s">"Attributes "</span> <span class="o">+</span> <span class="n">map</span> <span class="o">+</span> <span class="s">" are not from a valid jwk"</span><span class="o">);</span>
		<span class="o">}</span>
		<span class="k">if</span><span class="o">(</span><span class="n">keyOps</span> <span class="k">instanceof</span> <span class="nc">String</span><span class="o">)</span> <span class="o">{</span>
			<span class="k">return</span> <span class="k">new</span> <span class="nf">Jwk</span><span class="o">(</span><span class="n">kid</span><span class="o">,</span> <span class="n">kty</span><span class="o">,</span> <span class="n">alg</span><span class="o">,</span> <span class="n">use</span><span class="o">,</span> <span class="o">(</span><span class="nc">String</span><span class="o">)</span> <span class="n">keyOps</span><span class="o">,</span> <span class="n">x5u</span><span class="o">,</span> <span class="n">x5c</span><span class="o">,</span> <span class="n">x5t</span><span class="o">,</span> <span class="n">values</span><span class="o">);</span>
		<span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
			<span class="k">return</span> <span class="k">new</span> <span class="nf">Jwk</span><span class="o">(</span><span class="n">kid</span><span class="o">,</span> <span class="n">kty</span><span class="o">,</span> <span class="n">alg</span><span class="o">,</span> <span class="n">use</span><span class="o">,</span> <span class="o">(</span><span class="nc">List</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;)</span> <span class="n">keyOps</span><span class="o">,</span> <span class="n">x5u</span><span class="o">,</span> <span class="n">x5c</span><span class="o">,</span> <span class="n">x5t</span><span class="o">,</span> <span class="n">values</span><span class="o">);</span>
		<span class="o">}</span>
	<span class="o">}</span>

	<span class="kd">private</span> <span class="nc">List</span><span class="o">&lt;</span><span class="nc">Jwk</span><span class="o">&gt;</span> <span class="nf">getAll</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">SigningKeyNotFoundException</span> <span class="o">{</span>
		<span class="nc">List</span><span class="o">&lt;</span><span class="nc">Jwk</span><span class="o">&gt;</span> <span class="n">jwks</span> <span class="o">=</span> <span class="nc">Lists</span><span class="o">.</span><span class="na">newArrayList</span><span class="o">();</span>
		<span class="nd">@SuppressWarnings</span><span class="o">(</span><span class="s">"unchecked"</span><span class="o">)</span> 
        <span class="kd">final</span> <span class="nc">List</span><span class="o">&lt;</span><span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Object</span><span class="o">&gt;&gt;</span> <span class="n">keys</span> <span class="o">=</span> <span class="o">(</span><span class="nc">List</span><span class="o">&lt;</span><span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Object</span><span class="o">&gt;&gt;)</span> <span class="k">this</span><span class="o">.</span><span class="na">keys</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="s">"keys"</span><span class="o">);</span>

		<span class="k">if</span> <span class="o">(</span><span class="n">keys</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">||</span> <span class="n">keys</span><span class="o">.</span><span class="na">isEmpty</span><span class="o">())</span> <span class="o">{</span>
			<span class="k">throw</span> <span class="k">new</span> <span class="nf">SigningKeyNotFoundException</span><span class="o">(</span><span class="s">"No keys found"</span><span class="o">,</span> <span class="kc">null</span><span class="o">);</span>
		<span class="o">}</span>

		<span class="k">try</span> <span class="o">{</span>
			<span class="k">for</span> <span class="o">(</span><span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Object</span><span class="o">&gt;</span> <span class="n">values</span> <span class="o">:</span> <span class="n">keys</span><span class="o">)</span> <span class="o">{</span>
				<span class="n">jwks</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">fromValues</span><span class="o">(</span><span class="n">values</span><span class="o">));</span>
			<span class="o">}</span>
		<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IllegalArgumentException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
			<span class="k">throw</span> <span class="k">new</span> <span class="nf">SigningKeyNotFoundException</span><span class="o">(</span><span class="s">"Failed to parse jwk from json"</span><span class="o">,</span> <span class="n">e</span><span class="o">);</span>
		<span class="o">}</span>
		<span class="k">return</span> <span class="n">jwks</span><span class="o">;</span>
	<span class="o">}</span>

	<span class="nd">@Override</span>
	<span class="kd">public</span> <span class="nc">Jwk</span> <span class="nf">get</span><span class="o">(</span><span class="nc">String</span> <span class="n">keyId</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">JwkException</span> <span class="o">{</span>
		<span class="kd">final</span> <span class="nc">List</span><span class="o">&lt;</span><span class="nc">Jwk</span><span class="o">&gt;</span> <span class="n">jwks</span> <span class="o">=</span> <span class="n">getAll</span><span class="o">();</span>
		<span class="k">if</span> <span class="o">(</span><span class="n">keyId</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">&amp;&amp;</span> <span class="n">jwks</span><span class="o">.</span><span class="na">size</span><span class="o">()</span> <span class="o">==</span> <span class="mi">1</span><span class="o">)</span> <span class="o">{</span>
			<span class="k">return</span> <span class="n">jwks</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
		<span class="o">}</span>
		<span class="k">if</span> <span class="o">(</span><span class="n">keyId</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
			<span class="k">for</span> <span class="o">(</span><span class="nc">Jwk</span> <span class="n">jwk</span> <span class="o">:</span> <span class="n">jwks</span><span class="o">)</span> <span class="o">{</span>
				<span class="k">if</span> <span class="o">(</span><span class="n">keyId</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">jwk</span><span class="o">.</span><span class="na">getId</span><span class="o">()))</span> <span class="o">{</span>
					<span class="k">return</span> <span class="n">jwk</span><span class="o">;</span>
				<span class="o">}</span>
			<span class="o">}</span>
		<span class="o">}</span>
		<span class="k">throw</span> <span class="k">new</span> <span class="nf">SigningKeyNotFoundException</span><span class="o">(</span><span class="s">""</span><span class="o">,</span> <span class="kc">null</span><span class="o">);</span>
	<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>In order to use this I just added a bit to my existing <code class="language-plaintext highlighter-rouge">SecurityConfig</code>:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Configuration</span>
<span class="nd">@EnableWebSecurity</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">SecurityConfig</span> <span class="kd">extends</span> <span class="nc">WebSecurityConfigurerAdapter</span> <span class="o">{</span>

	<span class="nd">@Value</span><span class="o">(</span><span class="s">"${jwt.url}"</span><span class="o">)</span>
	<span class="kd">private</span> <span class="nc">String</span> <span class="n">jwtUrl</span><span class="o">;</span>

	<span class="nd">@Autowired</span>
	<span class="kd">private</span> <span class="nc">Environment</span> <span class="n">environment</span><span class="o">;</span>

	<span class="nd">@Bean</span>
	<span class="kd">public</span> <span class="nc">JwtAuthenticationProvider</span> <span class="nf">jwtAuthenticationProvider</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">IOException</span> <span class="o">{</span>
		<span class="nc">Set</span><span class="o">&lt;</span><span class="nc">JwtAuthenticationProvider</span><span class="o">.</span><span class="na">JwtAuthorizer</span><span class="o">&gt;</span> <span class="n">authorizers</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HashSet</span><span class="o">();</span>
		<span class="kd">final</span> <span class="nc">JwkProvider</span> <span class="n">jwkProvider</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">UrlJwkProvider</span><span class="o">(</span><span class="no">URI</span><span class="o">.</span><span class="na">create</span><span class="o">(</span><span class="n">jwtUrl</span><span class="o">+</span><span class="s">"/.well-known/jwks.json"</span><span class="o">).</span><span class="na">toURL</span><span class="o">());</span>
		<span class="n">authorizers</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="k">new</span> <span class="nc">JwtAuthorizer</span><span class="o">(</span><span class="n">jwkProvider</span><span class="o">,</span> <span class="n">jwtUrl</span><span class="o">));</span>

        <span class="c1">// We don't want to have this enabled normally</span>
        <span class="c1">// We need to inject the different accepted JWT authorization source into our JwtAuthenticationProvider</span>
        <span class="c1">// The reason </span>
		<span class="k">if</span><span class="o">(</span><span class="nc">ArrayUtils</span><span class="o">.</span><span class="na">contains</span><span class="o">(</span><span class="n">environment</span><span class="o">.</span><span class="na">getActiveProfiles</span><span class="o">(),</span> <span class="s">"test"</span><span class="o">))</span> <span class="o">{</span>
			<span class="nc">ClassPathResource</span> <span class="n">r</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ClassPathResource</span><span class="o">(</span><span class="s">"/jwks.json"</span><span class="o">);</span>
			<span class="kt">byte</span><span class="o">[]</span> <span class="n">bytes</span> <span class="o">=</span> <span class="nc">IOUtils</span><span class="o">.</span><span class="na">toByteArray</span><span class="o">(</span><span class="n">r</span><span class="o">.</span><span class="na">getInputStream</span><span class="o">());</span>
			<span class="nc">JwkProvider</span> <span class="n">localProvider</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">LocalJwkProvider</span><span class="o">(</span><span class="k">new</span> <span class="nc">ByteArrayInputStream</span><span class="o">(</span><span class="n">bytes</span><span class="o">));</span>
			<span class="n">authorizers</span><span class="o">.</span><span class="na">add</span><span class="o">(</span>
				<span class="k">new</span> <span class="nc">JwtAuthenticationProvider</span><span class="o">.</span><span class="na">JwtAuthorizer</span><span class="o">(</span><span class="n">localProvider</span><span class="o">,</span> <span class="s">"http://localhost"</span><span class="o">)</span>
			<span class="o">);</span>
		<span class="o">}</span>

		<span class="k">return</span> <span class="k">new</span> <span class="nf">JwtAuthenticationProvider</span><span class="o">(</span><span class="n">authorizers</span><span class="o">);</span>
	<span class="o">}</span>

	<span class="nd">@Bean</span>
	<span class="kd">public</span> <span class="nc">AuthenticationManager</span> <span class="nf">authenticationManager</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">IOException</span> <span class="o">{</span>
		<span class="k">return</span> <span class="k">new</span> <span class="nf">ProviderManager</span><span class="o">(</span>
			<span class="nc">Lists</span><span class="o">.</span><span class="na">newArrayList</span><span class="o">(</span>
				<span class="n">jwtAuthenticationProvider</span><span class="o">(),</span> <span class="n">serviceAuthenticationProvider</span><span class="o">()</span>
			<span class="o">)</span>
		<span class="o">);</span>
	<span class="o">}</span>

    <span class="c1">// Other code...</span>
<span class="o">}</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">authenticationManager()</code> allows you to have multiple <code class="language-plaintext highlighter-rouge">AuthenticationProvider</code> instances for different types of <code class="language-plaintext highlighter-rouge">Authentication</code> you might need.
This configuration enables you to keep your production authentication as a valid means of authenticating if you want.
While this isn’t common, at times I will be working with a local copy of production data and want to try something out myself locally with real credentials but no negative system impact.
This is especially useful when debugging an issue and trying to replicate the issue.
With the way I have designed it as far as the sytem</p>

<p>To begin this you will need to generate your <code class="language-plaintext highlighter-rouge">jwks.json</code> file. There is a nice free <a href="https://mkjwk.org">site</a> available that will help you do this without any fuss.
Once you have that <code class="language-plaintext highlighter-rouge">jwks.json</code> file<br />
The library you are going to want to use on the front-end is <code class="language-plaintext highlighter-rouge">jsrsasign</code>.
Here is a little JavaScript library to generate a token.</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">$</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">jquery</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">_</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">lodash</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">KJUR</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">jsrsasign</span><span class="dl">'</span><span class="p">).</span><span class="nx">KJUR</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">RSAKey</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">jsrsasign</span><span class="dl">'</span><span class="p">).</span><span class="nx">RSAKey</span><span class="p">;</span>


<span class="kd">function</span> <span class="nx">random</span><span class="p">(</span><span class="nx">num</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">nums</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">range</span><span class="p">(</span><span class="mi">48</span><span class="p">,</span> <span class="mi">57</span><span class="p">);</span>
    <span class="kd">var</span> <span class="nx">lettersU</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">range</span><span class="p">(</span><span class="mi">65</span><span class="p">,</span> <span class="mi">90</span><span class="p">);</span>
    <span class="kd">var</span> <span class="nx">lettersL</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">range</span><span class="p">(</span><span class="mi">97</span><span class="p">,</span> <span class="mi">122</span><span class="p">);</span>

    <span class="kd">var</span> <span class="nx">all</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">union</span><span class="p">(</span><span class="nx">nums</span><span class="p">,</span> <span class="nx">lettersL</span><span class="p">,</span> <span class="nx">lettersU</span><span class="p">);</span>

    <span class="kd">var</span> <span class="nx">str</span> <span class="o">=</span> <span class="dl">''</span><span class="p">;</span>
    <span class="k">for</span><span class="p">(</span><span class="nx">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="nx">i</span><span class="o">&lt;=</span> <span class="nx">num</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="kd">var</span> <span class="nx">index</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">random</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">all</span><span class="p">.</span><span class="nx">length</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
        <span class="kd">var</span> <span class="nx">val</span> <span class="o">=</span> <span class="nx">all</span><span class="p">[</span><span class="nx">index</span><span class="p">];</span>
        <span class="nx">str</span> <span class="o">+=</span> <span class="nb">String</span><span class="p">.</span><span class="nx">fromCodePoint</span><span class="p">(</span><span class="nx">val</span><span class="p">)</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="nx">str</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">function</span> <span class="nx">generateToken</span><span class="p">(</span><span class="nx">payload</span><span class="p">,</span> <span class="nx">key</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// Replace your key id</span>
    <span class="kd">var</span> <span class="nx">header</span> <span class="o">=</span> <span class="p">{</span><span class="na">alg</span><span class="p">:</span> <span class="dl">'</span><span class="s1">RS256</span><span class="dl">'</span><span class="p">,</span> <span class="na">kid</span><span class="p">:</span> <span class="dl">'</span><span class="s1">KEY_ID</span><span class="dl">'</span><span class="p">};</span>
    <span class="kd">var</span> <span class="nx">sHeader</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">header</span><span class="p">);</span>
    <span class="kd">var</span> <span class="nx">sPayload</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">payload</span><span class="p">);</span>
    <span class="kd">var</span> <span class="nx">sJWT</span> <span class="o">=</span> <span class="nx">KJUR</span><span class="p">.</span><span class="nx">jws</span><span class="p">.</span><span class="nx">JWS</span><span class="p">.</span><span class="nx">sign</span><span class="p">(</span><span class="dl">"</span><span class="s2">RS256</span><span class="dl">"</span><span class="p">,</span> <span class="nx">sHeader</span><span class="p">,</span> <span class="nx">sPayload</span><span class="p">,</span> <span class="nx">key</span><span class="p">);</span>

    <span class="k">return</span> <span class="nx">sJWT</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">function</span> <span class="nx">createTestCredentials</span><span class="p">(</span><span class="nx">username</span><span class="p">,</span> <span class="nx">groups</span><span class="p">,</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">cb</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">username</span> <span class="o">==</span> <span class="dl">'</span><span class="s1">undefined</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
        <span class="nx">username</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">test</span><span class="dl">'</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">if</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">key</span> <span class="o">==</span> <span class="dl">'</span><span class="s1">undefined</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
        <span class="nx">key</span> <span class="o">=</span> <span class="nx">getPem</span><span class="p">();</span>
    <span class="p">}</span>

    <span class="kd">var</span> <span class="nx">rsa</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">RSAKey</span><span class="p">();</span>
    <span class="nx">rsa</span><span class="p">.</span><span class="nx">readPrivateKeyFromPEMString</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>

    <span class="kd">var</span> <span class="nx">tNow</span> <span class="o">=</span> <span class="nx">KJUR</span><span class="p">.</span><span class="nx">jws</span><span class="p">.</span><span class="nx">IntDate</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">now</span><span class="dl">'</span><span class="p">);</span>
    <span class="kd">var</span> <span class="nx">tEnd</span> <span class="o">=</span> <span class="nx">KJUR</span><span class="p">.</span><span class="nx">jws</span><span class="p">.</span><span class="nx">IntDate</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">now + 1day</span><span class="dl">'</span><span class="p">);</span>

    <span class="kd">var</span> <span class="nx">payload</span> <span class="o">=</span> <span class="p">{</span>
        <span class="dl">'</span><span class="s1">iss</span><span class="dl">'</span><span class="p">:</span> <span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">protocol</span><span class="o">+</span><span class="dl">"</span><span class="s2">://</span><span class="dl">"</span><span class="o">+</span><span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">host</span><span class="p">,</span>
        <span class="dl">'</span><span class="s1">iat</span><span class="dl">'</span><span class="p">:</span> <span class="nx">tNow</span><span class="p">,</span>
        <span class="dl">'</span><span class="s1">username</span><span class="dl">'</span><span class="p">:</span> <span class="nx">username</span><span class="p">,</span>
        <span class="dl">'</span><span class="s1">jti</span><span class="dl">'</span><span class="p">:</span> <span class="nx">random</span><span class="p">(</span><span class="mi">50</span><span class="p">),</span>
        <span class="dl">'</span><span class="s1">exp</span><span class="dl">'</span><span class="p">:</span> <span class="nx">tEnd</span><span class="p">,</span>
        <span class="dl">'</span><span class="s1">cognito:groups</span><span class="dl">'</span><span class="p">:</span> <span class="nx">groups</span>
    <span class="p">};</span>

    <span class="kd">var</span> <span class="nx">res</span> <span class="o">=</span> <span class="nx">generateToken</span><span class="p">(</span><span class="nx">payload</span><span class="p">,</span> <span class="nx">rsa</span><span class="p">);</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">Test token generated</span><span class="dl">'</span><span class="p">);</span>

    <span class="k">if</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">cb</span> <span class="o">!==</span> <span class="dl">'</span><span class="s1">undefined</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
        <span class="nx">cb</span><span class="p">(</span><span class="nx">res</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="nx">res</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">function</span> <span class="nx">storeTestCredentials</span><span class="p">(</span><span class="nx">token</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">token</span><span class="dl">'</span><span class="p">,</span> <span class="nx">token</span><span class="p">);</span>
<span class="p">}</span>

<span class="kd">function</span> <span class="nx">createAndStoreTestCredentials</span><span class="p">(</span><span class="nx">username</span><span class="p">,</span> <span class="nx">groups</span><span class="p">,</span> <span class="nx">key</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nx">createTestCredentials</span><span class="p">(</span><span class="nx">username</span><span class="p">,</span> <span class="nx">groups</span><span class="p">,</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">storeTestCredentials</span><span class="p">);</span>
<span class="p">}</span>

<span class="kd">function</span> <span class="nx">getPem</span><span class="p">()</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">url</span><span class="p">;</span>
    <span class="k">if</span><span class="p">(</span><span class="nx">_</span><span class="p">.</span><span class="nx">isEqual</span><span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">host</span><span class="p">,</span> <span class="dl">'</span><span class="s1">localhost</span><span class="dl">'</span><span class="p">))</span> <span class="p">{</span>
        <span class="nx">url</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">http://localhost/test.pem</span><span class="dl">'</span><span class="p">;</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="nx">url</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">protocol</span><span class="o">+</span><span class="dl">'</span><span class="s1">://</span><span class="dl">'</span><span class="o">+</span><span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">host</span><span class="o">+</span><span class="dl">'</span><span class="s1">/test.pem</span><span class="dl">'</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span>
        <span class="na">type</span><span class="p">:</span> <span class="dl">"</span><span class="s2">GET</span><span class="dl">"</span><span class="p">,</span>
        <span class="na">url</span><span class="p">:</span> <span class="nx">url</span><span class="p">,</span>
        <span class="na">async</span><span class="p">:</span> <span class="kc">false</span>
    <span class="p">}).</span><span class="nx">responseText</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">module</span> <span class="o">!==</span> <span class="dl">'</span><span class="s1">undefined</span><span class="dl">'</span> <span class="o">&amp;&amp;</span> <span class="k">typeof</span> <span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">!==</span> <span class="dl">'</span><span class="s1">undefined</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="p">{</span>
        <span class="na">createTestCredentials</span><span class="p">:</span> <span class="nx">createTestCredentials</span><span class="p">,</span>
        <span class="na">createAndStoreTestCredentials</span><span class="p">:</span> <span class="nx">createAndStoreTestCredentials</span><span class="p">,</span>
        <span class="na">getPem</span><span class="p">:</span> <span class="nx">getPem</span>
    <span class="p">};</span>
<span class="p">}</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">testAuth</span> <span class="o">=</span> <span class="nx">module</span><span class="p">.</span><span class="nx">exports</span><span class="p">;</span>
</code></pre></div></div>

<p>So you will need to serve the <code class="language-plaintext highlighter-rouge">test.pem</code> file locally. 
If you used the “mkjwk” site I listed above you will need to extract the private key from the JSON and put it as a file.
The net result of using this will produce a JWT object that you are signing yourself but in all other ways will work with cognito or really anything else that generates a JWT token.</p>

<p>I have two different ways that I use this. The first way is just “Fake Login” which just creates a token with the <code class="language-plaintext highlighter-rouge">ADMIN</code> role and “test” as the username.
I use this when I really just need to get into the system and either don’t care or don’t want to be troubled with thinking about the exact roles I need at the moment.
The other approach is where I specify the exact roles or groups. Either way its the the same here.</p>

<p>«««&lt; HEAD</p>
<h2 id="support-for-granting-roles-and-permission-dynamically">Support for granting roles and permission dynamically</h2>
<p>=======</p>
<h1 id="support-for-granting-roles-and-permission-dynamically-1">Support for granting roles and permission dynamically</h1>
<blockquote>
  <blockquote>
    <blockquote>
      <blockquote>
        <blockquote>
          <blockquote>
            <blockquote>
              <p>staging
This is the more complex functionality that requires both knowledge of Spring Security as well how Spring Framework operates.
I’m going to give you the outline of the approach now. Quite simply we want to be able to give users access to certain roles and permission but not all the time.
Really, we want them to be able to perform operation A, B, and C. 
Normally knowing that operation A requires permission X, Y, and Z any attempt to invoke operation A without the requisite permission would yield in a 403.
Operation A is already protected by requiring permission W. We don’t want the user to have general permissions X, Y, and Z on a normal basis, but we do want them to be able to invoke operation A.
What you would have to do is grant the user permissions X, Y, and Z prior to the execution of operation A and remove them once the invocation has completed.</p>
            </blockquote>
          </blockquote>
        </blockquote>
      </blockquote>
    </blockquote>
  </blockquote>
</blockquote>

<p>Let’s see the very simple annotation I created:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Target</span><span class="o">({</span><span class="nc">ElementType</span><span class="o">.</span><span class="na">METHOD</span><span class="o">,</span> <span class="nc">ElementType</span><span class="o">.</span><span class="na">TYPE</span><span class="o">})</span>
<span class="nd">@Retention</span><span class="o">(</span><span class="nc">RetentionPolicy</span><span class="o">.</span><span class="na">RUNTIME</span><span class="o">)</span>
<span class="kd">public</span> <span class="nd">@interface</span> <span class="nc">Grants</span> <span class="o">{</span>
	<span class="nc">Permission</span><span class="o">[]</span> <span class="nf">value</span><span class="o">()</span> <span class="k">default</span> <span class="o">{};</span>
	<span class="nc">Role</span><span class="o">[]</span> <span class="nf">roles</span><span class="o">()</span> <span class="k">default</span> <span class="o">{};</span>
	<span class="nc">String</span> <span class="nf">name</span><span class="o">()</span> <span class="k">default</span> <span class="s">""</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div></div>

<p>What I have done with this is created a simple <code class="language-plaintext highlighter-rouge">@Aspect</code> that has a <code class="language-plaintext highlighter-rouge">@Before</code> and <code class="language-plaintext highlighter-rouge">@After</code> <code class="language-plaintext highlighter-rouge">JointPoint</code> advice.
Simply enough I created a base <code class="language-plaintext highlighter-rouge">Authentication</code> interface called <code class="language-plaintext highlighter-rouge">GrantingAuthentication</code> which extends the standard <code class="language-plaintext highlighter-rouge">Authentication</code> interface.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">interface</span> <span class="nc">GrantingAuthentication</span> <span class="kd">extends</span> <span class="nc">Authentication</span> <span class="o">{</span>
	<span class="nc">Collection</span><span class="o">&lt;</span><span class="nc">GrantedAuthority</span><span class="o">&gt;</span> <span class="nf">getAuthorities</span><span class="o">();</span>

	<span class="kt">void</span> <span class="nf">addAuthority</span><span class="o">(</span><span class="nc">Collection</span><span class="o">&lt;</span><span class="nc">GrantedAuthority</span><span class="o">&gt;</span> <span class="n">authorities</span><span class="o">);</span>
	<span class="kt">void</span> <span class="nf">removeAuthorities</span><span class="o">(</span><span class="nc">Collection</span><span class="o">&lt;</span><span class="nc">Authority</span><span class="o">&gt;</span> <span class="n">authorities</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>

<p>With this interface you need to modify any of your <code class="language-plaintext highlighter-rouge">Authentication</code> implementations to implement these functions.
Using this interface your aspect component can simply add the appropriate authorities (roles or permissions) prior to invocation. 
One thing that you need to be careful of is to keep track of what authorities you added, otherwise you might remove authorities that the user actual has outside of the grant.</p>

<p>«««&lt; HEAD</p>
<h2 id="service-token">Service Token</h2>
<p>=======</p>
<h1 id="service-token-1">Service Token</h1>
<blockquote>
  <blockquote>
    <blockquote>
      <blockquote>
        <blockquote>
          <blockquote>
            <blockquote>
              <p>staging
To handle the service token need there is a very simple and elegant solution. Use the <code class="language-plaintext highlighter-rouge">SecurityContextRepository</code> interface.
Both the JWT and the service token take use the <code class="language-plaintext highlighter-rouge">Authorization</code> header with the value prefixed by <code class="language-plaintext highlighter-rouge">Bearer</code>. 
With that all you need to do is in the <code class="language-plaintext highlighter-rouge">SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder)</code> function obtain the token from the header. 
Then if the token is one of the defined service tokens then just use <code class="language-plaintext highlighter-rouge">SecurityContextHolder.setContext(context)</code> to populate a security context with the appropriate authorities.
If the token is not for a service token then use the <code class="language-plaintext highlighter-rouge">PreAuthenticatedAuthenticationJsonWebToken.usingToken(token)</code> call. 
The Auth0 JWT implementation already uses this approach <a href="https://github.com/auth0/auth0-spring-security-api/blob/master/lib/src/main/java/com/auth0/spring/security/api/BearerSecurityContextRepository.java">here</a>.</p>
            </blockquote>
          </blockquote>
        </blockquote>
      </blockquote>
    </blockquote>
  </blockquote>
</blockquote>

<p>«««&lt; HEAD</p>
<h2 id="summary">Summary</h2>
<p>This approach has served my purposes quite well, and I have used several aspects of this approach in many other projects. 
Reusing good solid architecture is the corner stone of a strong foundation that is essential everywhere and all the time.
This resource is in no way exhaustive or intended to be complete. I hope some things here might help someone else with similar needs as myself or my organziation.
As always. comments and questions are always welcome. Enjoy, and make beautiful code.
=======</p>
<h1 id="summary-1">Summary</h1>
<p>This approach has served my purposes quite well, and I have used several aspects of this approach in many other projects. 
Reusing good solid architecture is the corner stone of a strong foundation that is essential everywhere and all the time.
This resource is in no way exhaustive or intended to be complete. I hope some things here might help someone else with similar needs as myself or my organziation.
As always. comments and questions are always welcome. Enjoy and make beautiful code.</p>
<blockquote>
  <blockquote>
    <blockquote>
      <blockquote>
        <blockquote>
          <blockquote>
            <blockquote>
              <p>staging</p>
            </blockquote>
          </blockquote>
        </blockquote>
      </blockquote>
    </blockquote>
  </blockquote>
</blockquote>]]></content><author><name>{&quot;login&quot;=&gt;&quot;dovidkopel&quot;, &quot;email&quot;=&gt;&quot;dovid@dovidkopel.com&quot;, &quot;display_name&quot;=&gt;&quot;Dovid Kopel&quot;, &quot;first_name&quot;=&gt;&quot;Dovid&quot;, &quot;last_name&quot;=&gt;&quot;Kopel&quot;}</name><email>dovid@dovidkopel.com</email></author><category term="aws" /><category term="authentication" /><category term="security" /><category term="jwt" /><category term="saml" /><category term="java" /><category term="spring-security" /><category term="spring-framework" /><summary type="html"><![CDATA[Recently I had to design and implement a solution that used a third-party user management system for authentication. I decided to use Amazon’s Cognito service, more specifically the User Pool aspect. The third-party service was able to work with SAML, and so does Cognito. Cognito’s output that you use is a JWT object. The backend system is written using Java 8 and Spring Framework and Spring Security.]]></summary></entry><entry><title type="html">Blockchain Smart-Contracts</title><link href="https://dovidkopel.com/2018/06/blockchain-smart-contracts" rel="alternate" type="text/html" title="Blockchain Smart-Contracts" /><published>2018-06-29T14:13:11+00:00</published><updated>2018-06-29T14:13:11+00:00</updated><id>https://dovidkopel.com/2018/06/blockchain-smart-contracts</id><content type="html" xml:base="https://dovidkopel.com/2018/06/blockchain-smart-contracts"><![CDATA[<p>I’ve been playing around with blockchain for non cryptocurrency. 
The smart-contract design is very intriguing as a true means to defining business contracts. 
I see a future where you have software engineers that specialize in building complex business contracts.</p>

<p>The speed and transaction capabilities of blockchain continue to be an issue. 
The big push for decentralization is to eliminate the major controlling factor like the Federal Reserve Bank. 
It should be noted that a recent article in <a href="https://www.technologyreview.com/s/610783/bitcoin-would-be-a-calamity-not-an-economy/">MIT Technology Review</a> actually suggested that this would actually have a larger negative impact from an economical perspective. 
I do not wish to debate the economics of a central bank for inflation concerns as this is not my expertise. 
I can say however, that whatever the outcome may be regarding currency this is not necessarily the case with smart-contracts or other blockchain applications.</p>

<p>I believe in decentralization through centralization with transparency and built-in checks and balances (programmatic regulation).
If the framers of the United States Constituion were drafting the doctrine of the new nation of America today can craft a technological solution that would faciliate the balance of power in our nation.
Imagine utilizing enterprise workflows and conditional logic to frame the scope of power for each branch of the government.
If I remember my <a href="https://www.youtube.com/watch?v=tyeJ55o3El0">Schoolhouse Rock video “I’m just a bill”</a> about how a bill is made into law there are lots of numbers but in the end the President has the ability to veto the bill.
That veto power would be built into the bill workflow. The matter of constituional law interpretation will become moot. 
If there is ambiguity in a programmatic contract a revision may be made according to the revision workflow process.</p>

<p>In the end the most important system is the integrity of the capability to update workflows and rules. 
The core system has roles and permissions, who may modify a given workflow or set of rules.
Each state has two senators. Since the senator is an internal matter as opposed to a national one.
Each state will have their own respective SSO system that will authorize the elected senator with the proper national credentials.
When a senator would vote in congress, they would be a trusted official through their respective state. I don’t know about you, but I just made CSPAN fun!</p>

<p>With my elaborate government scenario let’s go back to my initial point, decentralization. 
You don’t need to be fully decentralized if you have a well architected system that has regulation and proper authorization built-in.
This doesn’t mean that there is a single mainframe like Fort Knox. You can have a co-located, distributed system that is self-contained.</p>

<p>The physical servers, databases and all the infrastructure are hardened and designed with extreme measures. The system is audited, and highly regulated. 
If you want to do a peer-to-peer concept you can also have regulation on top of the decentralization. Depending on the needs of the data isolation, the transaction may be more or less tightly bound.
This is commonly called eventually consistant. Without getting into too much detail I would see a torrent style of nodes with tracker ids attributed to a given component of the network. 
In other words as the overall data corpus grows the number of identified pieces incease in size and require a certain health ratio in order to maintain operational. 
The data is protected with the same sort of cryptographic measures that are put in place for a block of blockchain.
In this case however, the signature of the block is built upon its previous blocks. A DAG (Directed Acyclical Graph) is a more appropriate data abstracction for this approach.
Using a DAG has been proposed for cryptocurrency as well. There of course it received pushback regarding the decentralization concerns.</p>

<p>One thing I need to point out about decentralization that is very important and non-trivial in nature. For those who are concerned about a nuclear event or some sort of worldwide event that shifts the power on a worldwide scale…and you are storing your wealth in cryptocurrency so that if your government is to fall your wealth is safe.
There is a very significant measure that is not accounted for. Even if you are storing your cryptocurrency locally, what are the chances of there being a structured national electric grid to provide power.
Having a generator won’t help if the government is truly in disarray. The extremely complex network that we call the Internet is not too resiliant at the core.</p>

<p>In the end their are risk and there is the likelihood of there occurence. 
I rather have a well designed self-regulating system that is centralized over the notion of complete anarchy sacraficing the integrity of the system.</p>]]></content><author><name>{&quot;login&quot;=&gt;&quot;dovidkopel&quot;, &quot;email&quot;=&gt;&quot;dovid@dovidkopel.com&quot;, &quot;display_name&quot;=&gt;&quot;Dovid Kopel&quot;, &quot;first_name&quot;=&gt;&quot;Dovid&quot;, &quot;last_name&quot;=&gt;&quot;Kopel&quot;}</name><email>dovid@dovidkopel.com</email></author><category term="blockchain" /><category term="cryptocurrency" /><category term="smart-contract" /><category term="workflows" /><category term="business rules" /><category term="decentralization" /><summary type="html"><![CDATA[I’ve been playing around with blockchain for non cryptocurrency. The smart-contract design is very intriguing as a true means to defining business contracts. I see a future where you have software engineers that specialize in building complex business contracts.]]></summary></entry><entry><title type="html">Moving Away From WordPress To Serverless</title><link href="https://dovidkopel.com/2018/05/moving-away-from-wordpress-to-serverless" rel="alternate" type="text/html" title="Moving Away From WordPress To Serverless" /><published>2018-05-11T00:00:00+00:00</published><updated>2018-05-11T00:00:00+00:00</updated><id>https://dovidkopel.com/2018/05/moving-away-from-wordpress-to-serverless</id><content type="html" xml:base="https://dovidkopel.com/2018/05/moving-away-from-wordpress-to-serverless"><![CDATA[<p>I had been using WordPress for well over a decade. It is a great product and has a lot of capabilities. 
It is also heavy, and complex if you really only need a simple blog. I generally write very technical content 
that makes using something like markdown preferable over a WYSIWYG or even HTML. I had still been hosting my blog and my domain names on GoDaddy,
back when that was the preferable choice. Having had a great deal of experience over the past number of years with AWS, I decided to look for a solution 
that would be easy and utilizing AWS.</p>

<p>It’s not surprising to me that AWS does not have a direct clone for WordPress managed blogs, nor should they.
I’ve said it many times, AWS is not for the novice. They have created LightSail (which I’ve never used) as an attempt to appease the novice.
They offer an instance image with some pre-configured options. I chose the WordPress option and clicked the “Next” button. It really is pretty simply, 
it is probably more complicated than what you would see in GoDaddy, but its a big step forward. They use a Bitnami image and it has directions how to manage your account.</p>

<p>Now I have no intention of using WordPress or LightSail, but I did want to take a look at it. Instead I wanted to simply use S3 and somehow use markdown.
I had experience with <a href="https://jekyllrb.com/">Jekyll</a> a bit in the past and was positive that it would satisfy my needs. I had at one time looked into using this service called <a href="https://www.siteleaf.com">SiteLeaf</a>, 
which was nice but for what you are paying for it seems like I can figure out another solution. 
GitHub is great and all, but I wanted to use AWS end to end, and because they charge next to nothing for code commit.</p>

<p>What I wanted was a simple way to write markdown and take advantage of any markdown <a href="https://github.com/planetjekyll/awesome-jekyll-plugins">plugins</a>. Now because this content is going to be generated and served statically the only processing that needed to be done was when updating or creating content. I wanted to have a development environment where I can write drafts as well as make changes to the site as needed. Ideally I wanted to be able to go to any computer login somewhere and be able to add an article on a whim. Not needing an IDE and an entire setup. This is much less important but something that I did think about.</p>

<p>I started to use AWS CodePipeline which would listen for commits on the respective <code class="language-plaintext highlighter-rouge">master</code> and <code class="language-plaintext highlighter-rouge">staging</code> branches. It is possible I am mistaken, but I didn’t find a way to make conditional branch that will only rebuild and deploy the respective branch. In fact I had to make two pipelines, one triggered by each branch. I decided whether or not you could do this with CodePipeline and I just couldn’t figure it out, that is an inherit flaw!</p>

<p>Let me go into what I was doing in the build process and give you some clarity. There is only a very fine difference between the development and production environments and that really didn’t need more than an environment variable to be flipped. I was hoping that I would override an environment variable in the pipeline prior to executing the build, but alas I could not find the means.</p>

<p>I knew that I was going to use a Docker image for the build process. 
I also quickly realized that I will need to have the <code class="language-plaintext highlighter-rouge">awscli</code> package in that image.
Technically I can just output it and have CodeBuild stick the artifact somewhere, but I wanted to use CodeBuild to “build” and “deploy”.
This is a very simple blog that didn’t require several stages like a more sophisticated system would.
Luckilly jekyll maintains  docker images that are up to date. Here is my Dockerfile below:</p>

<p><a href="https://github.com/dovidkopel/aws-jekyll/blob/master/Dockerfile"><strong>Dockerfile</strong></a></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>FROM jekyll/jekyll:3.8.0

RUN apk --no-cache update &amp;&amp; \
    apk --no-cache add gcc g++ make build-base python3 py3-pip ca-certificates curl groff less git py-yaml &amp;&amp; \
    pip3 --no-cache-dir install --upgrade pip &amp;&amp; \
    rm -rf /var/cache/apk/*

RUN pip3 --no-cache-dir install awscli

ADD Gemfile /root/Gemfile
ADD Gemfile.lock /root/Gemfile.lock

RUN cd /root &amp;&amp; \
    /usr/gem/bin/bundle install

CMD sh
</code></pre></div></div>
<p>All I really did here was add python support and the aws tool. I also added the <code class="language-plaintext highlighter-rouge">Gemfile</code> and <code class="language-plaintext highlighter-rouge">Gemfile.lock</code>.
If you don’t know ruby, that has the list of dependencies. 
You may ask the question why would I install all of the dependencies now, wouldn’t I want install them at the time of the build?
Yes, of course. This installs them, and then at the time of build if there are any changes or new packages they get installed. 
This reduced the time of the build immensely and was a perfect enhancement.</p>

<p>Initially for my <code class="language-plaintext highlighter-rouge">buildspec.yml</code> I had two simple steps I ran the <code class="language-plaintext highlighter-rouge">jekyll build</code> command, and then I used <code class="language-plaintext highlighter-rouge">aws s3 cp</code> to upload the generated files to s3.
I had a simple environment variable <code class="language-plaintext highlighter-rouge">BUCKET</code> which was set with a default to <code class="language-plaintext highlighter-rouge">dovidkopel.com</code>. The idea was when running a development build the <code class="language-plaintext highlighter-rouge">BUCKET</code> environment variable would be overridden to <code class="language-plaintext highlighter-rouge">staging.dovidkopel.com</code>.
Unfortunately right away I realized that being able to have pretty urls with no extension and preserve and urls that have existed in the past would be difficult.</p>

<p>Here is my <code class="language-plaintext highlighter-rouge">buildspec.yml</code>:</p>

<p><a href="https://github.com/dovidkopel/aws-jekyll/blob/master/buildspec.yml"><strong>buildspec.yml</strong></a></p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">version</span><span class="pi">:</span> <span class="m">0.2</span>

<span class="na">phases</span><span class="pi">:</span>
  <span class="na">install</span><span class="pi">:</span>
    <span class="na">commands</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">python3 jekyll-build.py</span>
      <span class="pi">-</span> <span class="s">python3 pre-upload.py</span>
      <span class="pi">-</span> <span class="s">aws s3 cp _site s3://$BUCKET/ --acl public-read --recursive</span>
      <span class="pi">-</span> <span class="s">python3 rename-html.py</span>

</code></pre></div></div>

<p>I wrote up a small python script that was used for the build to give me a little more flexibility.</p>

<p><a href="https://github.com/dovidkopel/aws-jekyll/blob/master/jekyll-build.py"><strong>jekyll-build.py</strong></a></p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">os</span>

<span class="n">bucket</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">[</span><span class="s">'BUCKET'</span><span class="p">]</span>
<span class="n">base_cmd</span> <span class="o">=</span> <span class="s">'/usr/local/bundle/bin/jekyll {}'</span>

<span class="k">if</span> <span class="n">bucket</span> <span class="o">==</span> <span class="s">'staging.dovidkopel.com'</span><span class="p">:</span>
    <span class="n">os</span><span class="p">.</span><span class="n">system</span><span class="p">(</span><span class="n">base_cmd</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="s">'build --drafts'</span><span class="p">))</span>
<span class="k">else</span><span class="p">:</span>
    <span class="n">os</span><span class="p">.</span><span class="n">system</span><span class="p">(</span><span class="n">base_cmd</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="s">'build'</span><span class="p">))</span>
</code></pre></div></div>

<p>The way I was going to serve the static content was to set the data with an <code class="language-plaintext highlighter-rouge">acl</code> of <code class="language-plaintext highlighter-rouge">public-read</code>.
Then you enable website hosting for that bucket. That gets you most of the way, you might have thought.
Initially I thought the only thing I would be missing is SSL since if I just used the s3 url and made my domain record a cname to point to it it would work.
I quickly realized that was a small problem in comparison to the index issue.
I knew I was going to use CloudFront more than anything as a easy way to add SSL to my blog.
CloudFront supports a “default root object”, in other words if you goto <code class="language-plaintext highlighter-rouge">dovidkopel.com</code> it will attempt to fetch <code class="language-plaintext highlighter-rouge">dovidkopel.com/index.html</code>.
The problem is that this was only supported on the root level. So a link like this: <code class="language-plaintext highlighter-rouge">https://dovidkopel.com/2016/11/mankind-is-not-a-simple-feature-vector</code> which is a really great article I wrote a few years back would not function properly.
I googled around a bit and found that I am not the first person to find this “annoyance” of CloudFront. 
There was some solutions proposed, but I came up with my own.</p>

<p>In the case of the url listed earlier the way that WordPress handled that was with a HTTP rewrite rule.
Neither S3 (without extreme measure) or CloudFront easily supported this. 
However, if uploaded the <code class="language-plaintext highlighter-rouge">mankind-is-not-a-simple-feature-vector.html</code> file into the <code class="language-plaintext highlighter-rouge">2016/11</code> directory and then rename the file it worked!
I tried a few different variations, uploading the file without an extension and specifying the content type.
There was an issue with S3 that I could not change the content-type of the file once it was uploaded. 
Therefore I successfully uploaded all of the files and then rename them as needed.</p>

<p>I wanted some additional features that were pretty url related. I need to support pagination of the main page: <code class="language-plaintext highlighter-rouge">https://dovidkopel.com/archives/page/2</code>.
I also wanted to support general archive by tag and chronology with indices.
I am using the <code class="language-plaintext highlighter-rouge">jekyll-archives</code> plugin. Here is part of my configuration:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">jekyll-archives</span><span class="pi">:</span>
  <span class="na">enabled</span><span class="pi">:</span> <span class="s">all</span>
  <span class="na">layout</span><span class="pi">:</span> <span class="s1">'</span><span class="s">archive'</span>
  <span class="na">layouts</span><span class="pi">:</span>
    <span class="na">year</span><span class="pi">:</span> <span class="s">year-archive</span>
    <span class="na">month</span><span class="pi">:</span> <span class="s">month-archive</span>
    <span class="na">day</span><span class="pi">:</span> <span class="s">day-archive</span>
    <span class="na">tag</span><span class="pi">:</span> <span class="s">tag-archive</span>
    <span class="na">category</span><span class="pi">:</span> <span class="s">category-archive</span>
  <span class="na">permalinks</span><span class="pi">:</span>
    <span class="na">title</span><span class="pi">:</span> <span class="s1">'</span><span class="s">/:year/:month/:title/'</span>
    <span class="na">year</span><span class="pi">:</span> <span class="s1">'</span><span class="s">/archives/date/:year/'</span>
    <span class="na">month</span><span class="pi">:</span> <span class="s1">'</span><span class="s">/archives/date/:year-:month/'</span>
    <span class="na">day</span><span class="pi">:</span> <span class="s1">'</span><span class="s">/archives/date/:year-:month-:day/'</span>
    <span class="na">tag</span><span class="pi">:</span> <span class="s1">'</span><span class="s">/archives/tag/:name/'</span>
    <span class="na">category</span><span class="pi">:</span> <span class="s1">'</span><span class="s">/archives/category/:name/'</span>
</code></pre></div></div>

<p>Now I wrote a little python script to handle some local renaming after generating the files but before the upload.
This made the renaming process on S3 much simpler.</p>

<p><a href="https://github.com/dovidkopel/aws-jekyll/blob/master/pre-upload.py"><strong>pre-upload.py</strong></a></p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">glob</span>
<span class="kn">import</span> <span class="nn">os</span>

<span class="k">def</span> <span class="nf">rename</span><span class="p">(</span><span class="n">f</span><span class="p">):</span>
	<span class="n">old</span> <span class="o">=</span> <span class="n">ff</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">replace</span><span class="p">(</span><span class="s">'/index.html'</span><span class="p">,</span> <span class="s">''</span><span class="p">)</span>
	<span class="n">ff</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">replace</span><span class="p">(</span><span class="s">'/index.html'</span><span class="p">,</span> <span class="s">'.html'</span><span class="p">)</span>
	<span class="k">print</span><span class="p">(</span><span class="s">'{} --&gt; {}'</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">ff</span><span class="p">))</span>
	<span class="n">os</span><span class="p">.</span><span class="n">rename</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">ff</span><span class="p">)</span>
	<span class="n">os</span><span class="p">.</span><span class="n">rmdir</span><span class="p">(</span><span class="n">old</span><span class="p">)</span>	
	
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">glob</span><span class="p">.</span><span class="n">glob</span><span class="p">(</span><span class="s">'_site/archives/page/*/index.html'</span><span class="p">,</span> <span class="n">recursive</span><span class="o">=</span><span class="bp">True</span><span class="p">):</span>
	<span class="n">rename</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>

<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">glob</span><span class="p">.</span><span class="n">glob</span><span class="p">(</span><span class="s">'_site/archives/date/*/index.html'</span><span class="p">,</span> <span class="n">recursive</span><span class="o">=</span><span class="bp">True</span><span class="p">):</span>
	<span class="n">rename</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
	
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">glob</span><span class="p">.</span><span class="n">glob</span><span class="p">(</span><span class="s">'_site/archives/tag/*/index.html'</span><span class="p">,</span> <span class="n">recursive</span><span class="o">=</span><span class="bp">True</span><span class="p">):</span>
	<span class="n">rename</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>	
</code></pre></div></div>

<p>Lastly, here is the rename script that I use for getting rid of the <code class="language-plaintext highlighter-rouge">.html</code> extensions while preserving the content type.</p>

<p><a href="https://github.com/dovidkopel/aws-jekyll/blob/master/rename-html.py"><strong>rename-html.py</strong></a></p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">glob</span>
<span class="kn">import</span> <span class="nn">os</span>

<span class="n">bucket</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">[</span><span class="s">'BUCKET'</span><span class="p">]</span>

<span class="k">def</span> <span class="nf">handle_file</span><span class="p">(</span><span class="n">f</span><span class="p">):</span>
	<span class="n">f</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">replace</span><span class="p">(</span><span class="s">'_site/'</span><span class="p">,</span> <span class="s">''</span><span class="p">)</span>
	<span class="n">ff</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">replace</span><span class="p">(</span><span class="s">'_site/'</span><span class="p">,</span> <span class="s">''</span><span class="p">)</span>
	<span class="n">ff</span> <span class="o">=</span> <span class="n">ff</span><span class="p">.</span><span class="n">replace</span><span class="p">(</span><span class="s">'.html'</span><span class="p">,</span> <span class="s">''</span><span class="p">)</span>
	
	<span class="n">os</span><span class="p">.</span><span class="n">system</span><span class="p">(</span><span class="s">'aws s3 mv s3://{}/{} s3://{}/{} --acl public-read --content-type "text/html"'</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">bucket</span><span class="p">,</span> <span class="n">f</span><span class="p">,</span> <span class="n">bucket</span><span class="p">,</span> <span class="n">ff</span><span class="p">))</span>
	
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">glob</span><span class="p">.</span><span class="n">glob</span><span class="p">(</span><span class="s">'_site/**/*.html'</span><span class="p">,</span> <span class="n">recursive</span><span class="o">=</span><span class="bp">True</span><span class="p">):</span>
	<span class="n">handle_file</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
</code></pre></div></div>

<p>The one piece I haven’t gotten to yet is how I got rid of CodePipeline. I created a very simple <a href="https://github.com/dovidkopel/aws-jekyll/blob/master/blog-code-commit-lambda.py">lambda</a> function.
This lambda had a trigger setup from CodeCommit on the <code class="language-plaintext highlighter-rouge">updateReference</code> event on the <code class="language-plaintext highlighter-rouge">master</code> or <code class="language-plaintext highlighter-rouge">staging</code> branches.
The lambda needs to have the permissions to invoke the build of course.</p>

<p>As for being able to write at any time I had been playing around with Cloud9. AWS bought Cloud9 recently and I initially really hated the idea.
I think that it still needs a lot of work but I think it help strike a balance for unifying the development environment and simplifying collaboration.
It is linked to an EC2 instance so it is capable of invoking commands as needed. It was sluggish (could have been the tiny instance) and had no git support built-in.
I even figured out how to share the workspace when authenticating via a SAML IDP.</p>

<p>For the time being I have been using <a href="https://stackedit.io/app">StackEdit</a> for jotting down markdown or I jump on Cloud9.</p>

<p><strong>All of the source code referenced here is available on github via <a href="https://github.com/dovidkopel/aws-jekyll">this</a> link.</strong></p>]]></content><author><name>{&quot;login&quot;=&gt;&quot;dovidkopel&quot;, &quot;email&quot;=&gt;&quot;dovid@dovidkopel.com&quot;, &quot;display_name&quot;=&gt;&quot;Dovid Kopel&quot;, &quot;first_name&quot;=&gt;&quot;Dovid&quot;, &quot;last_name&quot;=&gt;&quot;Kopel&quot;}</name><email>dovid@dovidkopel.com</email></author><category term="aws" /><category term="data storage" /><category term="database" /><category term="serverless" /><summary type="html"><![CDATA[I had been using WordPress for well over a decade. It is a great product and has a lot of capabilities. It is also heavy, and complex if you really only need a simple blog. I generally write very technical content that makes using something like markdown preferable over a WYSIWYG or even HTML. I had still been hosting my blog and my domain names on GoDaddy, back when that was the preferable choice. Having had a great deal of experience over the past number of years with AWS, I decided to look for a solution that would be easy and utilizing AWS.]]></summary></entry><entry><title type="html">AWS Kinesis and data streams</title><link href="https://dovidkopel.com/2018/04/aws-kinesis-and-data-streams" rel="alternate" type="text/html" title="AWS Kinesis and data streams" /><published>2018-04-17T13:42:02+00:00</published><updated>2018-04-17T13:42:02+00:00</updated><id>https://dovidkopel.com/2018/04/aws-kinesis-and-data-streams</id><content type="html" xml:base="https://dovidkopel.com/2018/04/aws-kinesis-and-data-streams"><![CDATA[<p>For large complex application system communication between services as well as from the external world is the backbone of your system infrastructure. I can go on for a while going into the various options for these types of systems and my many experiences with each of them. However, I want to focus on the managed services that AWS offers for this purpose. I’m going to run through SQS/SNS, Amazon MQ, and Kinesis. Each of these deserve their own in-depth analysis and all truly have great merit on their own.</p>

<p>The first system while technically are two separate systems, are often utilized together. SQS is a simple queuing system, and SNS is the simple notification system. SNS messages must go somewhere, to a subscribed endpoint which may be sms, lambda, email, or an sqs queue. SNS does not support the capacity to reply to messages as well as anything more than a completely static topic. In more versatile messaging systems nuances such as wildcards or hierarchical systems may be used to allow for a powerful routing system.</p>

<p>SNS may automatically trigger a Lambda which makes SNS very powerful. SNS with a lambda trigger is a single point of failure for message execution. If that lambda was erroneous for any reason that would result in that message being lost, which for many systems is not an option.</p>

<p>SQS cannot be trigger a Lambda, a queue must be polled or scanned and items processed. Ideally AWS should have the capacity to automatically call a Lambda upon an item being added to queue. I would design the system such that depending on the calls return status would determine whether or not the item should be removed from the queue or not.</p>

<p>I think to address some of the matters I have pointed out AWS came out with their own managed AMQP: Amazon MQ. I’m pretty disappointed, I know that a number of AWS services are probably heavily tweaked open source software under the covers, but this almost seemed lazy. There are two options for the broker size, and that is all. I would’ve hoped to see a truly scalable “managed service” that would closer reflect SQS. I’m not sure if they released Amazon MQ just to satisfy some customers who wanted an official MQ as opposed to maintaining an instance themselves. Now with ECS Fargate I have a hard time justifying the difference between the two. With that said, is this way of saying that this is a technology that they do not wish to further invest in.</p>

<p>Stream processing is no simple task, but it’s even more complex if you want to process the stream in a modular way. Do you have one huge monolithic function that analyzes that entire block? More importantly how do you deal with a block? You may buffer the data but that doesn’t guarantee that you will be able to process the data immediately. I’m especially thinking of encrypted data that may vary by the type of data. Yes, you can use KMS but that will only work for encrypting the data stream on a whole. What if you want to be able to use many different types of data each with their own encryption mechanisms or keys.</p>

<p>What if you want to allow external parties to push data on to your stream. As a way to consume data much like a third party would push data via any other transport protocol. We can grant the third party user access to encrypt on the kms key for the given stream. Then you may consume this external stream breaking it down into the correct category finding its appropriate destination. You need to judge based on how large the raw data is, but it is likely that it is not worth passing it around the network.</p>

<p>In general when playing around with technologies like this, I will want to push very hard limits to figure out what use cases are appropriate. Depending on the size of the initial payload, number of consumers, need for transactions, etc., you can establish a matrix that will help decide whether a technology is a good fit or not for a given use case, or at all.</p>

<p>Back in the day when data storage was expensive, we would try to avoid storing redundant data. Now, storage is really cheap, and even processing power isn’t too bad. Concurrency and time are still a factor. Even if you have data stored in several places, and many processors to evaluate the data with a given condition doesn’t mean you will not run into non-linear issues with the data eval. In general I’ve found the best approach is more clearly defining your storage, processing, and analytics needs. Separating functions with focus on single intention not all functionality, like a crappy multi-function printer.</p>

<p>This type of approach followed to its logical conclusion would yield a MapReduce style system. This isn’t a bad thing, it is a bad thing if your steps in your pipeline are redundant, and not optimized. For batch processing of data using a Hadoop style cluster even with a smarter workflow is still very clumsy. Even using Apache Spark which attempts to better organize and process your data, is still quite clumsy.</p>

<p>When dealing with YARN or Mesos, or any type of job distributing system it really doesn’t understand your data needs or the relationship between the workflow steps, and the conditions in between those steps. Apache Spark evolves slightly in this manner, more intelligently grouping together data for it to be processed with greater performance.</p>

<p><strong>Let’s pretend your data is 100 bytes long.</strong></p>

<ol>
  <li>Do you need the entire 100 bytes at one time? (Decryption, signature validation, checksum etc.)</li>
  <li>Yes.
    <ol>
      <li>Okay you need the initial data at one time. Let’s assume you want to decrypt it.</li>
      <li>It probably makes sense to hash, very, and decrypt it once and then send it through its channels. Depending on the number of consumers, the number of checks, and nature of encryption this will usually be your better option.</li>
    </ol>
  </li>
  <li>No.
    <ol>
      <li>If your data is not encrypted, or</li>
      <li>Do you need to process the data serially?</li>
      <li>Do you need the output of each step, or only the previous step?</li>
    </ol>
  </li>
  <li>Can you process the 100 bytes in parallel?
    <ol>
      <li>Depending on the size of the payload and the number of subsequent operations you need to perform on it recognize that it may be cheaper to extract some needed information about the data, store it in an in memory datastore, or S3 (whatever), then reference the data and retrieve it for the remaining usages. What it all boils down to is being smarter with your data on the onset.</li>
    </ol>
  </li>
</ol>

<p>If you have a very simple data flow that you can glean based on the first few bytes of data you can augment your flow accordingly. The greatest problem with this type of data processing at scale is balancing the ability to easily change the workflow operations while maintaining performance.</p>

<p>I’ve done some extensive R&amp;D with Scala and some expression languages. I’ve found that if your plan of action well is defined in advance, even dynamic in nature like code may be able to derive how to best execute your steps to maximize efficiency, and minimize operating costs.</p>

<p>If you are at all familiar with the IoC notion, or Inversion of Control design paradigm. This is commonly used in systems to define how to handle dependencies. Instead of attempting to populate all its needed dependencies, a service will accurately declare them relying on the underlying infrastructure to keep its contract much like you’d expect of an API. This same technique may be utilized for data processing as well. Imagine if you were to indicate that a given method accepts <code class="language-plaintext highlighter-rouge">Unencrypted</code> data, and that the data must be provided <code class="language-plaintext highlighter-rouge">Sequentially</code>. You don’t want a step to dictate exactly where it must be, but it is logical for it to indicate what it may and may not do. For instance, a step that may convert data from one format to another should ideally have one input and one output. Not only the number of possible inputs can be defined, but also matters that will determine data flow. This knowledge can be used to determine where certain more ambiguous or unspecified matters may be determined based on the best contextual decision.</p>

<p>I’m inclined to approach utilizing this sort of stream processing as a transport, not a solution. In general, I feel that AWS services are better to be looked at as infrastructure and not fully developed solutions. Depending on the size of your organization and the speed in which you need to move you may choose to embrace this notion or not. I know that there are large organizations which almost only use EC2 instances, and that’s all. I believe there is a healthy balance between only using AWS (or any cloud vendor for that vendor) as a data center replacement, and high level services. When you choose scalability and uptime over features as a given you really need to ask yourself is that really the case? Is there a way you can make a reliable more versatile solution that can be as reliable or close enough?</p>

<p>Please take this to heart, more “9”’s doesn’t mean much if you have plenty of bugs, poor security and other wonderful problems. Don’t let stupid metrics be the primary inspiration to how you budget your time and money. Prioritize your problems, you don’t have the be the cool kid in the class with the biggest numbers.</p>]]></content><author><name>{&quot;login&quot;=&gt;&quot;dovidkopel&quot;, &quot;email&quot;=&gt;&quot;dovid@dovidkopel.com&quot;, &quot;display_name&quot;=&gt;&quot;Dovid Kopel&quot;, &quot;first_name&quot;=&gt;&quot;Dovid&quot;, &quot;last_name&quot;=&gt;&quot;Kopel&quot;}</name><email>dovid@dovidkopel.com</email></author><category term="aws" /><category term="data storage" /><category term="database" /><summary type="html"><![CDATA[For large complex application system communication between services as well as from the external world is the backbone of your system infrastructure. I can go on for a while going into the various options for these types of systems and my many experiences with each of them. However, I want to focus on the managed services that AWS offers for this purpose. I’m going to run through SQS/SNS, Amazon MQ, and Kinesis. Each of these deserve their own in-depth analysis and all truly have great merit on their own.]]></summary></entry><entry><title type="html">Mankind is not a simple feature vector</title><link href="https://dovidkopel.com/2016/11/mankind-is-not-a-simple-feature-vector" rel="alternate" type="text/html" title="Mankind is not a simple feature vector" /><published>2016-11-20T16:35:47+00:00</published><updated>2016-11-20T16:35:47+00:00</updated><id>https://dovidkopel.com/2016/11/mankind-is-not-a-simple-feature-vector</id><content type="html" xml:base="https://dovidkopel.com/2016/11/mankind-is-not-a-simple-feature-vector"><![CDATA[<p>I’m not going to talk about politics, but I do want to talk about <a href="http://www.argmin.net/2016/11/14/fall-of-big-data/">this article</a> I found on one of my many feeds. I will summarize this extremely briefly. This guy was so baffled by the election outcome and the poor pollster statistics and generally how this wasn’t predicted with machine learning and the sort.</p>

<p>Anyone who knows me, knows that i hate the term “Artificial Intelligence” I remember some expert in the industry who closer compared it to “slightly less dumb”. I have written a number of other articles expressing how we are very far away from anything that is truly intelligent, by much any definition. Tools Ike Watson and DeepMind are impressive highly refined tools that have been fed incredibly large data sets so that it could either be trained or train itself.</p>

<p>It is not at all a surprise that predictions were so far off. When dealing with decision making in general most people choose choice A because they align themselves with many of the principles, philosophies, and ideas. That is at least what we wish people did. The reality is the things that are not about the “issues” are a great deal more important than people may think. People are not Vulcans; they are not making every action or even most of the actions that they perform weighing in all of the possible outcomes and the long term versus the short term benefits.</p>

<p>People are emotional and erratic creatures. People are bigots, racists, or so open minded that they have no actual opinions. We live in a world where people must be politically correct and are shunned for deviation. Money and power go hand in hand provide ample leverage to many scenarios. Corruption is not Republican or Democratic phenomenon, it is a part of humanity. Our nation and its capitalistic mindset is one of the greatest things that make us a unique and great nation. Regulation from monopolies is a way to limit that the gross power a company may posses should only reach so far.</p>

<p>The power of leverage from a huge conglomerate had over the government is tremendous. A true system or checks and balances that provides independence to the capitalistic nature of commerce as well as the freedom for a nation to govern itself is not any easy task in any way. It seems evident that in our over 240 years it is still far from perfect.</p>

<p>What we need to realize is a machine model, and statistics that are collected only account for the features and dimensoins that were taken into account. The nuances of what a single person wants let alone a nation of millions of them is simply impossible without first grasping the human factor. The incredible thing that define each and every person who lives on this planet.</p>

<p>I hope that our understanding of ourselves as well as our capacity to teach our machine models improves so that we can better harness and sustain the wonderful qualities of mankind.</p>]]></content><author><name>{&quot;login&quot;=&gt;&quot;dovidkopel&quot;, &quot;email&quot;=&gt;&quot;dovid@dovidkopel.com&quot;, &quot;display_name&quot;=&gt;&quot;Dovid Kopel&quot;, &quot;first_name&quot;=&gt;&quot;Dovid&quot;, &quot;last_name&quot;=&gt;&quot;Kopel&quot;}</name><email>dovid@dovidkopel.com</email></author><category term="artificial intelligence" /><category term="ai" /><category term="emotion" /><category term="human" /><category term="machine learning" /><summary type="html"><![CDATA[I’m not going to talk about politics, but I do want to talk about this article I found on one of my many feeds. I will summarize this extremely briefly. This guy was so baffled by the election outcome and the poor pollster statistics and generally how this wasn’t predicted with machine learning and the sort.]]></summary></entry><entry><title type="html">Functional programming in the enterprise world</title><link href="https://dovidkopel.com/2016/09/functional-programming-in-the-enterprise-world" rel="alternate" type="text/html" title="Functional programming in the enterprise world" /><published>2016-09-18T17:55:45+00:00</published><updated>2016-09-18T17:55:45+00:00</updated><id>https://dovidkopel.com/2016/09/functional-programming-in-the-enterprise-world</id><content type="html" xml:base="https://dovidkopel.com/2016/09/functional-programming-in-the-enterprise-world"><![CDATA[<p>Recently I have been heavily using Apache Spark. For those of you who don’t know Spark is a very powerful system for working with data and parallel that is written in the Scala language. Scala is not new, but certainly on the “newer” end of the spectrum. Today new languages are coming out all the time so 12 years is fairly long. What many people find attractive about Scala, at least I do is the fact that it runs on the popular JVM. In fact a developer may be able to write code in Java and interact with code that was written in Scala. The challenge is striking the balance between closeness to Java and still providing whatever it is that the creators of the language hope to achieve.</p>

<p>I am a big believer in Object Oriented software design and development. I’m not saying that every project in the world needs to be written exactly the same, as they all have different requirements. I will say that for enterprise software the level of adaptability is truly best achieved with levels of modularity as well as abstraction. In truth, if you can achieve the principles that an enterprise architect looks at in a technology it may be something to be considered. In the past languages like LISP such as Haskell, were never geared towards the enterprise as their mathematical background and dynamic typing didn’t fit the bill for the type of type safety compilation and code reuse that has been found in other enterprise technologies. In general I like languages that aim for simplicity but at the same time aren’t overly opinonated. I recently read a rant about the Go language for the lack of support of assertions because the language creators felt that people used assertions incorrectly, not like Java chose to avoid pointers because of their inherit nature to cause errors. This is an example of a language being dumbed down or muted, with that said I really like many aspects of Go.</p>

<p>I’ve read a number of articles about so called “veteran” developers who have ditched OOP to embrace some sort of functional language. Complaining that the design principles of OOP aren’t applicable and don’t work. I even <a href="https://blogs.msdn.microsoft.com/alfredth/2011/03/22/object-oriented-programming-is-dead/">read recently</a> that a college professor from Carnegie Mellon removed OOP from the syllabus for freshman. I don’t necessarily think that is too awful, but I do think problem decomposition that one would do when designing an OOP system is not only very helpful but also useful. Not everything easily fits into a “map” or a “reduce”. I can’t speak for all people, but I think that OOP is more natural to the domain than functional. If you truly understand the domain and how to break apart a problem into single scoped entities you will find simplicity and elegance.</p>

<p>With that being said, I think that for parallelism functional programming has always been faster and more efficient. I do however think that there is room to bridge the gap. Scala is a multi-paradigm language, not just functional. I believe it is that aspect that can truly bring something special to the table. Technologies like Spark still require a more or less functional approach. There are layers like Dataframes and graphs that attempt to abstract some of the functional aspects from the developer. What I haven’t yet seen is what Hibernate and other ORM technologies did for SQL, with respect to large scale functional parallelism. I think once we bridge that gap that will be the holy grail for enterprise software. I look forward to seeing how these technologies continue to evolve and mature.</p>]]></content><author><name>{&quot;login&quot;=&gt;&quot;dovidkopel&quot;, &quot;email&quot;=&gt;&quot;dovid@dovidkopel.com&quot;, &quot;display_name&quot;=&gt;&quot;Dovid Kopel&quot;, &quot;first_name&quot;=&gt;&quot;Dovid&quot;, &quot;last_name&quot;=&gt;&quot;Kopel&quot;}</name><email>dovid@dovidkopel.com</email></author><category term="functional programming" /><category term="java" /><category term="jvm" /><category term="oop" /><category term="scala" /><category term="spark" /><summary type="html"><![CDATA[Recently I have been heavily using Apache Spark. For those of you who don’t know Spark is a very powerful system for working with data and parallel that is written in the Scala language. Scala is not new, but certainly on the “newer” end of the spectrum. Today new languages are coming out all the time so 12 years is fairly long. What many people find attractive about Scala, at least I do is the fact that it runs on the popular JVM. In fact a developer may be able to write code in Java and interact with code that was written in Scala. The challenge is striking the balance between closeness to Java and still providing whatever it is that the creators of the language hope to achieve.]]></summary></entry></feed>