<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Flare</title>
    <description>The latest articles on Forem by Flare (@flare).</description>
    <link>https://forem.com/flare</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F5884%2Fb87b5dbe-ce81-4bce-948a-62c58cc8eeb3.png</url>
      <title>Forem: Flare</title>
      <link>https://forem.com/flare</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/flare"/>
    <language>en</language>
    <item>
      <title>Habits of Great Developers: The Underrated Power of Small, Frequent Merge Requests</title>
      <dc:creator>Benoit Doyon</dc:creator>
      <pubDate>Tue, 10 Jun 2025 15:31:19 +0000</pubDate>
      <link>https://forem.com/flare/habits-of-great-developers-the-underrated-power-of-small-frequent-merge-requests-2232</link>
      <guid>https://forem.com/flare/habits-of-great-developers-the-underrated-power-of-small-frequent-merge-requests-2232</guid>
      <description>&lt;p&gt;Trying to measure developer productivity is a famously difficult and often misguided effort. IBM’s historic attempt to gauge output by lines of code written is perhaps the most notorious example. It rewarded verbosity over clarity and activity over outcome.&lt;/p&gt;

&lt;p&gt;Yet despite the limitations of rigid metrics, some patterns consistently emerge when you observe highly effective software engineers. At Flare, one habit we’ve seen repeatedly among our best developers is simple and powerful:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;They make small and frequent merge requests.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this post, we’ll unpack why this behavior works so well and how it supports better collaboration, faster iteration, and stronger product delivery.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Small, Frequent MRs Work
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. They Reflect Deep Understanding
&lt;/h3&gt;

&lt;p&gt;At Flare, we work within a &lt;a href="https://dev.to/flare/shapeup-at-flare-a-game-changer-for-project-management-1k4h"&gt;Shape Up&lt;/a&gt;-inspired product development framework. A large part of each cycle is spent on shaping and understanding the problem. By the time execution begins, the scope is usually de-risked and well understood.&lt;/p&gt;

&lt;p&gt;When a developer has that deep understanding, they naturally break the work down into clear, manageable chunks. Each merge request becomes one of those chunks: focused, self-contained, and purposeful.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. They’re Easier to Review and Safer to Ship
&lt;/h3&gt;

&lt;p&gt;Large change sets are difficult to review thoroughly. Even experienced teammates can miss important details when too much is packed into a single MR. In contrast, small MRs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Surface issues earlier
&lt;/li&gt;
&lt;li&gt;Make reviews faster and more focused
&lt;/li&gt;
&lt;li&gt;Reduce the risk of regressions
&lt;/li&gt;
&lt;li&gt;Are easier to revert if something goes wrong
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This supports faster iteration and higher confidence in production releases.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. They Encourage a Collaborative Mindset
&lt;/h3&gt;

&lt;p&gt;A steady stream of small MRs creates rhythm in a team’s workflow. It encourages collaboration, builds trust, and makes progress visible.&lt;/p&gt;

&lt;p&gt;Being stuck on something for too long, however, is a red flag. In one of the most effective teams I’ve worked with, we had a simple rule: if you were blocked for more than 40 minutes, raise a flag. That one principle saved days of frustration and kept momentum high.&lt;/p&gt;




&lt;h2&gt;
  
  
  What About Big Refactors?
&lt;/h2&gt;

&lt;p&gt;None of this means that large, exploratory change sets have no value. Sometimes, a big refactor is the best way to learn. I often create a scratch branch where I pull apart a system to understand it better.&lt;/p&gt;

&lt;p&gt;But that’s not what I submit for review.&lt;/p&gt;

&lt;p&gt;Instead, I use that learning to map out a sequence of clean, logical steps. Then I go back and start fresh, delivering the solution through a set of small, testable MRs. That’s when the real progress begins.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary: Strong Developers, Small Chunks
&lt;/h2&gt;

&lt;p&gt;Here are a few things you’ll often see among high-performing developers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Merge requests are small, focused, and submitted regularly
&lt;/li&gt;
&lt;li&gt;Blockers are raised early and solved collaboratively
&lt;/li&gt;
&lt;li&gt;Large refactors are used for learning, but final changes are delivered incrementally
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Frequent, small merge requests are more than a habit. They’re the outcome of thoughtful problem-solving and deliberate communication. If you want to move fast and build confidently, this is one of the clearest paths forward.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Why LLMs Won't Replace My Junior Developers</title>
      <dc:creator>Benoit Doyon</dc:creator>
      <pubDate>Fri, 07 Mar 2025 14:09:53 +0000</pubDate>
      <link>https://forem.com/flare/why-llms-wont-replace-my-junior-developers-3pao</link>
      <guid>https://forem.com/flare/why-llms-wont-replace-my-junior-developers-3pao</guid>
      <description>&lt;p&gt;We're hiring quite a bit at Flare these days, so I spend a few minutes each day on LinkedIn to scout candidates. It seems that the algorithm has decided that endless posts describing the downfall of the junior developers in the face of machine learning are going to capture my engagement. I guess it's not wrong in a sense, as it has compelled me to explain exactly why LLMs won't be replacing the junior developers in my team anytime soon.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning and Growth Require Real Experience
&lt;/h2&gt;

&lt;p&gt;Junior developers aren't here just to ship code. They're learning how to think critically, solve complex problems and collaborate with the team. My AI assistant might write a function given a decent prompt, but it won't be as useful when debugging production, communicating technical ideas, or adapt to ever-changing project requirements. I can't overstate how happy it makes me when I give an assignment to a junior developer and instead of coming up with a flawed merge request, they come back with a question instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Context Matters
&lt;/h2&gt;

&lt;p&gt;LLMs are great at generating snippets of code, but they lack the full context of a project's architecture, business logic, and long-term goals. Junior developers, on the other hand, learn the nuances of the codebase, understand why certain design decisions were made, and can make informed contributions that align with the bigger picture. I don't value junior developers as code monkeys, but rather as wielders of a fresh pair of eyes with which to look at a problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Over-Reliance on AI Can Be Risky
&lt;/h2&gt;

&lt;p&gt;Using LLMs as a crutch can lead to complacency. Developers, especially those early in their careers, need to understand why code works, not just what code to write. Developing these habits is what allows them to grow into competent senior developers. If juniors skip the learning process and rely solely on AI-generated solutions, they miss out on developing critical problem-solving skills. It's like using a calculator without ever learning basic math. Sure, you might get an answer, but it all breaks down when confronting changing requirements and a nuanced playground. When building products, this basically means all the time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Junior Developers Bring Long-Term Value
&lt;/h2&gt;

&lt;p&gt;Investing in junior developers isn't just about the present, it's about the future. Today's juniors are tomorrow's leaders. By nurturing their growth, you're building a team that understands your product deeply, values continuous improvement, and can mentor the next generation. More senior developers also gain a lot by having junior members in the team. Flexing those mentoring muscles and learning how to become a multiplier in a team, instead of being a single contributor, is how developers unlock greater potential.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;LLMs are powerful tools, and I encourage my team to explore them as a way to enhance productivity. But they're just that—tools. They can't replace the curiosity, growth potential, and human connection that junior developers bring.&lt;/p&gt;

&lt;p&gt;If you're interested in fostering an environment where junior developers can thrive, we're currently hiring a lead for our platform team. Send me a message and I'll be happy to chat about building an engineering culture where humans are at the center of everything.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://flare.bamboohr.com/hiring/jobs/73" rel="noopener noreferrer"&gt;https://flare.bamboohr.com/hiring/jobs/73&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Why A Great Developer Onboarding Matters</title>
      <dc:creator>Benoit Doyon</dc:creator>
      <pubDate>Tue, 18 Feb 2025 13:32:24 +0000</pubDate>
      <link>https://forem.com/flare/why-a-great-developer-onboarding-matters-93i</link>
      <guid>https://forem.com/flare/why-a-great-developer-onboarding-matters-93i</guid>
      <description>&lt;p&gt;I think most technical onboarding experiences throughout my career have looked something like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Receive a company laptop&lt;/li&gt;
&lt;li&gt;Clone the code repository&lt;/li&gt;
&lt;li&gt;Find the latest person who's been through the painful process of setting up a local environment, and hope that they remember what they're doing, especially when trying to attempt to debug the inevitable errors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A poor onboarding process can lead to confusion and frustration, setting the wrong tone for a developer's experience at your company. On the other hand, a well-structured onboarding process ensures they start with clarity and confidence. At Flare, I believe we've found the key to effective onboarding: structured guidance, hands-on experience, and continuous support. And to be honest, it's nothing complicated. These small investments will go a long way to get developers started on the right foot.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Cost of Poor Onboarding
&lt;/h2&gt;

&lt;p&gt;Hiring great developers is hard. Once you hire someone who's excited to get started, the last thing you want to do is to be a hurdle to their momentum.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Long ramp-up times&lt;/strong&gt; – New hires spend weeks or months just figuring out where things are and how to get started.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frustration and disengagement&lt;/strong&gt; – Without clear guidance, new developers can feel lost or undervalued.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Higher turnover&lt;/strong&gt; – If onboarding is disorganized, developers may leave before they ever hit their stride.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Team slowdowns&lt;/strong&gt; – A poorly onboarded developer pulls others away from their work for constant questions and troubleshooting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the flip side, a strong onboarding process accelerates learning, boosts confidence, and makes developers feel like they belong.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Makes a Great Developer Onboarding Experience?
&lt;/h2&gt;

&lt;p&gt;A great onboarding process goes beyond just documentation and checklists. Here’s what truly makes a difference:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Clear Expectations from Day One
&lt;/h3&gt;

&lt;p&gt;Developers should know exactly what’s expected of them, what success looks like, and how they’ll get there. A structured onboarding plan with milestones helps keep everything on track. At Flare, since we work with Shape Up cycles, new developers typically follow a specific learning curve. You spend one cycle onboarding and learning, you spend one cycle executing and contributing within a team, and finally you are ready to lead a cycle and champion a project.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Easy Access to Tools and Information
&lt;/h3&gt;

&lt;p&gt;Nothing slows down a new hire like missing credentials or outdated documentation. We make sure to automate setup where possible and ensure essential resources (like API keys, test environments, and architecture diagrams) are easy to find. As part of our onboarding, the new hire updates the onboarding documents to ensure they remain accurate and relevant. This ensures that they are always up-to-date, and free of any ambiguity.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Hands-on Learning and Small Wins
&lt;/h3&gt;

&lt;p&gt;Instead of drowning developers in documentation, we let them start with small, meaningful tasks. Fixing a minor bug or improving documentation in their first week builds confidence and helps them understand the codebase faster. The way we do this at Flare is with something we call quests, which are sample tasks that everyone does (ex: change the color of a button in the UI, implement a new API listing feature flags). This way you can get relevant comments from everyone on the team, while also making sure your development setup functions correctly in a controlled environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Mentorship and Support
&lt;/h3&gt;

&lt;p&gt;Assigning a buddy or mentor gives new hires a go-to person for questions and guidance. This helps them integrate socially and technically into the team more smoothly. On top of the buddy system, we make sure new developers spend a day shadowing each member of the team during their second week. This gives them exposure to different workflows, coding styles, and problem-solving approaches, helping them understand how various parts of the team collaborate and function together.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Team and Culture Integration
&lt;/h3&gt;

&lt;p&gt;Onboarding isn’t just about code. We want to help new developers connect with their team, understand the company’s culture, and feel like they belong. Casual introductions, team lunches, and pairing sessions make a big difference. We tend to group new hires in cohorts, and we plan a welcome lunch, as well as introductions during the weekly company all-hands.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Payoff: Faster, Happier, and More Effective Teams
&lt;/h2&gt;

&lt;p&gt;Investing in great onboarding isn’t just about making new hires feel good, it’s about making your entire team more effective. Developers ramp up faster, contribute sooner, and stay longer. A smooth onboarding experience signals that your company values its people and sets them up for success from day one.&lt;/p&gt;

&lt;p&gt;If you want a stronger, more engaged engineering team, start with how you welcome them. Investing in great onboarding leads to faster productivity, higher retention, and a more cohesive team. Take the time to refine your process, and you’ll see the impact in every aspect of your development culture. Onboarding isn’t just the first step, it’s the foundation for everything that follows.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Why (and how) we hire software development interns</title>
      <dc:creator>Benoit Doyon</dc:creator>
      <pubDate>Fri, 23 Aug 2024 15:16:47 +0000</pubDate>
      <link>https://forem.com/flare/why-and-how-we-hire-software-development-interns-47ao</link>
      <guid>https://forem.com/flare/why-and-how-we-hire-software-development-interns-47ao</guid>
      <description>&lt;p&gt;Intern recruitment season is upon us! At Flare, we typically hire 2-3 interns each semester, with one joining one of our development teams. As we prepare to welcome a new cohort, we’re also gearing up to recruit for the following semester. Here’s an inside look at what an engineering internship at Flare entails, the benefits we gain as an organization, and how we ensure we recruit top-quality candidates.&lt;/p&gt;

&lt;h2&gt;
  
  
  What an Internship at Flare Looks Like
&lt;/h2&gt;

&lt;p&gt;Before an intern starts at Flare, we’ve already identified a team that aligns well with their skills and interests. During the interview process, we discuss their previous experience, areas of interest, and what they hope to learn. However, once they’re more familiar with what we do at Flare, they’re free to choose the team they wish to join.&lt;/p&gt;

&lt;p&gt;Interns undergo the same onboarding process as our full-time developers. The onboarding starts with an introduction to the company, where they learn about our mission, meet leadership from every department, and get a comprehensive overview of our operations. Following this, they dive into developer-specific onboarding, which includes a series of "quests." These quests are essentially sample tasks that cover various aspects of development, ensuring that interns have correctly set up their environment and tools. Throughout this process, they are guided by a "buddy" and supported by their assigned team. Typically, within the first two weeks, interns are ready to tackle a real issue.&lt;/p&gt;

&lt;p&gt;Once onboarded, interns are fully integrated into their development teams, participating in our development cycle (&lt;a href="https://dev.to/flare/shapeup-at-flare-a-game-changer-for-project-management-1k4h"&gt;see our ShapeUp article for more details&lt;/a&gt;). During their semester at Flare, interns work on two full development cycles. This means they will contribute to two meaningul and time-bound projects. The first project helps them get up to speed, gradually taking on larger tasks as they become more comfortable and independent. By the end of their internship, they’ve gained the experience of delivering two increments of user value—an ideal experience for budding engineers.&lt;/p&gt;

&lt;p&gt;In summary, our interns are treated as full team members, working alongside experienced developers on meaningful projects. We set realistic expectations based on their experience level but ensure they are fully immersed in our development process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why We Hire Interns
&lt;/h2&gt;

&lt;p&gt;Hiring interns offers numerous benefits beyond just increasing development velocity. While gaining additional hands on deck is valuable, the true benefits lie elsewhere.&lt;/p&gt;

&lt;p&gt;Firstly, recruiting interns is an excellent way to engage our team in the recruitment process. It’s a low-stakes entry point that allows team members to gain experience in hiring, particularly those who might be hesitant about recruiting more experienced professionals. Our internship hiring process is shorter and less time-consuming than hiring full-time developers, making it an ideal starting point.&lt;/p&gt;

&lt;p&gt;Once interns join the team, it’s a fantastic opportunity for team members to develop mentoring skills. Mentoring is a crucial skill that improves communication, processes, and team interactions far beyond the scope of the internship program. In my view, this is the greatest benefit of having interns.&lt;/p&gt;

&lt;p&gt;Moreover, providing a great internship experience is important to us. It not only benefits the interns themselves but also contributes to a positive environment that makes future recruitment easier. It's a great pipeline to cultivate to ensure a steady flow of well-trained junior developers joining the team.&lt;/p&gt;

&lt;h2&gt;
  
  
  How We Recruit Great Candidates
&lt;/h2&gt;

&lt;p&gt;Our recruitment process for interns consists of two main parts. First, we conduct a one-hour "fit" interview. This interview allows us to discuss the candidate’s experience, explain what an internship at Flare entails, and answer any questions they may have. If there’s a mutual fit, we move on to the next step.&lt;/p&gt;

&lt;p&gt;The second step is a technical interview. We believe it’s essential to see interns code to ensure they can be productive within our development teams. Given the steep learning curve and the complexity of our distributed systems, we focus on onboarding interns to our way of doing things rather than teaching the basics of software engineering. Therefore, we prioritize candidates with prior experience and assess their capabilities during this interview.&lt;/p&gt;

&lt;p&gt;While coding interviews can be daunting, we strive to make ours as comfortable as possible. We ask candidates to solve a simple problem involving around a dozen lines of code, conducted live over video chat. Though this might seem stressful, we allow candidates to use any programming language, tools, or documentation they’re comfortable with, including Google and language docs. They can also ask questions, and we guide them as needed. Our goal is to simulate real work, where we act more as colleagues than interviewers. Feedback suggests that while candidates may feel nervous initially, they quickly relax and enjoy the exercise.&lt;/p&gt;

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

&lt;p&gt;Thanks for sticking with me through this overview of software development internships at Flare! If you’ve got thoughts on our process, I’d love to hear them. And if you’re looking for an internship yourself, don’t hesitate to reach out—we’re always on the lookout for great talent. &lt;a href="https://flare.io/company/careers/" rel="noopener noreferrer"&gt;https://flare.io/company/careers/&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>ShapeUp at Flare: A Game-Changer for Project Management</title>
      <dc:creator>Benoit Doyon</dc:creator>
      <pubDate>Tue, 23 Jul 2024 17:12:29 +0000</pubDate>
      <link>https://forem.com/flare/shapeup-at-flare-a-game-changer-for-project-management-1k4h</link>
      <guid>https://forem.com/flare/shapeup-at-flare-a-game-changer-for-project-management-1k4h</guid>
      <description>&lt;p&gt;I first encountered ShapeUp during one of my initial interviews for a position at Flare. My soon-to-be manager mentioned, “We’re using a methodology that works well for us, but you might not have heard of it before.” With over 10 years of software development experience under my belt, I was skeptical. “If there was a better way to do things, surely I’d have heard of it,” I thought. Little did I know, ShapeUp would fundamentally change my approach to project management and team dynamics.&lt;/p&gt;

&lt;p&gt;Before extolling the virtues of ShapeUp, let me provide some context. Throughout my career, I’ve been part of many dysfunctional teams, as well as some exceptional ones that delivered far beyond the norm. I spent a great deal of time thinking about this and trying to replicate those particular conditions in every team I was part of. I was a solid SCRUM advocate. I tend to think that being “agile” works better with a lowercase “a”, and the guiding principle is to craft a process that best suits your situation. However, despite my dedication to SCRUM, I frequently encountered roadblocks in getting teams to perform well.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Enter ShapeUp&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;ShapeUp, created by BaseCamp, is a methodology that we use to run projects at Flare. The ShapeUp book is a mandatory read for all new employees, and while it’s concise, I’ll outline the key principles we follow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Work is scheduled in 8-week cycles&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Each cycle consists of a 6-week project period followed by a 2-week cooldown.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;No backlog&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Instead, we have a “shaping” process where top-of-mind tasks are defined into projects.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Blurry project definitions&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;The problem statement and goals are clear, but the team is trusted to build the solution within the time constraints. Developers are assigned a problem to solve rather than a ticket to complete.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Cooldown periods&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Developers have the freedom to work on whatever they want during the cooldown.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;ShapeUp’s simplicity and elegance lie in the details. Here are the main advantages we’ve experienced:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Meaningful increments&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;We always focus on the most important tasks, and 6 weeks is sufficient to build something substantial.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Big-picture focus&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Developers are trusted with significant liberty in solving problems, fostering creativity and innovation.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;No “just one more sprint…” death march&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;With ShapeUp, projects conclude after 6 weeks, preventing endless extensions and allowing for fresh starts in the next cycle.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Protected developer time&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Developers’ time is safeguarded to focus, free from external interruptions during projects and unnecessary justifications during cooldown.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Cooldowns Are Awesome&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Cooldowns are a beloved aspect of ShapeUp at Flare. Business stakeholders often remark, “There’s so much great stuff getting done, we should do cooldowns all the time.”&lt;/p&gt;

&lt;p&gt;Cooldowns provide the perfect opportunity to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Conduct retrospectives and plan the next cycle.&lt;/li&gt;
&lt;li&gt;De-risk upcoming projects.&lt;/li&gt;
&lt;li&gt;Fix bugs, perform meaningful refactorings, and work on passion projects.&lt;/li&gt;
&lt;li&gt;Experiment with new technologies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Developers get really excited about cooldowns, and the business as well. It turns out that if you hire developers that care about their craft and let them run loose for 2 weeks once in a while, they contribute meaningfully.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Additional Advantages&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Interns at Flare, typically with us for a 4-month semester, greatly benefit from the ShapeUp cycles. Aligning our cycles with university semesters and holidays allows interns to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Onboard at the start of a cycle.&lt;/li&gt;
&lt;li&gt;Contribute meaningfully to a project.&lt;/li&gt;
&lt;li&gt;Apply their knowledge in a subsequent project, experiencing two full cycles during their internship.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Usually seeing is believing, but something feels right even when just being introduced to the concept of ShapeUp. People immediately perk up when we mention how we work during interviews. Candidates we’ve hired that are experiencing ShapeUp for the first time are now becoming ambassadors. After a year with ShapeUp, I know I’m sold.&lt;/p&gt;

&lt;p&gt;ShapeUp is more than just a project management approach. It changes the way we approach problem-solving and team dynamics, fostering trust, creativity, and enabling significant progress. If you’re struggling with your current methodology or just curious about alternatives, I highly recommend giving ShapeUp a try. It might just revolutionize your team’s productivity and satisfaction as it has for us at Flare.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Incorporating LLMs Into Cybersecurity</title>
      <dc:creator>Alexandre Viau</dc:creator>
      <pubDate>Thu, 21 Sep 2023 15:21:48 +0000</pubDate>
      <link>https://forem.com/flare/incorporating-llms-into-cybersecurity-1eh1</link>
      <guid>https://forem.com/flare/incorporating-llms-into-cybersecurity-1eh1</guid>
      <description>&lt;p&gt;Bombarded with multiple alerts coming from multiple disconnected services, security analysts continue to struggle with alert fatigue. While they need context about threats facing their organizations, many also find identifying the right context challenging. &lt;/p&gt;

&lt;p&gt;Today, companies expect security analysts to be experts in everything from the technical to the criminal underground. In reality, this just isn’t possible. However, large language models (LLMs) excel at summarizing large quantities of data, offering security teams a starting point for their analyses.&lt;/p&gt;

&lt;p&gt;Flare uses LLMs to help analysts get the insights and answers they need quickly so that they can filter out false positives and focus on what really matters. &lt;/p&gt;

&lt;h1&gt;
  
  
  Using LLMs to Provide Context
&lt;/h1&gt;

&lt;p&gt;LLMs can help separate out important context. Typically we see two different use cases: non-technical and technical. &lt;/p&gt;

&lt;h2&gt;
  
  
  Non-Technical Context from LLMs
&lt;/h2&gt;

&lt;p&gt;From a non-technical point of view, LLMs adapt well to given slang language. They understand the context and quickly summarize information, eliminating the need to do Google searches. &lt;/p&gt;

&lt;p&gt;First, criminal underground chatter uses slang that has a different meaning within their community when compared to the technical community. &lt;/p&gt;

&lt;p&gt;For example, they often use the term “logs,” referring to stolen usernames and passwords. Technical professionals usually recognize this term as the digital record of activity happening in their environment. With the prompt, LLMs can “translate” this for you. &lt;/p&gt;

&lt;p&gt;Second, LLMs can help you understand what an application does. For example, when threat actors post stolen credentials for sale, they usually name the application. By explaining the application, LLM tools make it easier to determine whether the stolen credentials pose a risk to your organization’s security posture. &lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Context from LLMs
&lt;/h2&gt;

&lt;p&gt;At a technical level, ChatGPT does an excellent job of helping analysts better identify real, exploitable risks to their environments. &lt;/p&gt;

&lt;p&gt;For example, when Flare identifies a GitHub match, the LLM can look at the code and understand whether the mention indicates a risk or not. When developers use a base template for an app rather than starting from scratch, they often make a copy and rename it for their company before they start working. Sometimes, these files may have a hardcoded password. However, this public facing hardcoded password poses little risk to the company until the developer starts modifying the code to build the company-specific application. &lt;/p&gt;

&lt;p&gt;When Flare detects the company name in GitHub, the LLM provides context around whether the match poses little risk because it was in a default config file or could indicate a problem because the developer made a modification. &lt;/p&gt;

&lt;h1&gt;
  
  
  Limitations of LLMs
&lt;/h1&gt;

&lt;p&gt;While LLMs provide various benefits, they also come with some limitations. LLMs analyze unstructured data which poses difficulties when writing prompts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Unstructured Data
&lt;/h2&gt;

&lt;p&gt;When inputting a query, the LLM has a hard time deciphering the difference between the question being asked and the data being supplied. For example, if you’re providing the text of a message and asking if it was written by a specific threat group, the LLM gets confused. It can often focus on the threat group’s name or a username in the prompt rather than analyzing the message’s text that you want to know about. &lt;/p&gt;

&lt;h2&gt;
  
  
  Input Size
&lt;/h2&gt;

&lt;p&gt;LLMs can limit the amount of data that it can summarize so choosing what information the prompt includes is critical.&lt;/p&gt;

&lt;p&gt;Although ChatGPT’s context window simulates a conversation to look human, the LLM doesn’t “remember” the beginning of conversations. If you engage in a long conversation, then it won’t be able to answer appropriately because it may not be accessing the original information, such as the threat actor's name. &lt;/p&gt;

&lt;p&gt;To get the most accurate actor profile possible, you need to choose the inputs carefully. Ideally, when an actor is active on the criminal underground and the clear web, you want to take a little bit of both. You need to combine some of the:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Oldest criminal underground activity&lt;/li&gt;
&lt;li&gt;Recent criminal underground activity &lt;/li&gt;
&lt;li&gt;Oldest clear web activity&lt;/li&gt;
&lt;li&gt;Recent clear web activity &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the right inputs, the model can fill the gaps, giving you a good high level view of what the threat actor does. &lt;/p&gt;

&lt;h2&gt;
  
  
  Source Code
&lt;/h2&gt;

&lt;p&gt;LLM models use tokenization that transforms texts into numbers which often means that ChatGPT can analyze less code in a given input than it can text. Consider the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CHAT GPT&lt;/li&gt;
&lt;li&gt;chat GPT&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While the human eye and mind reads these as the same two phrases, the LLM model transforms following data point into a separate number:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;chat&lt;/li&gt;
&lt;li&gt;CHAT&lt;/li&gt;
&lt;li&gt;G&lt;/li&gt;
&lt;li&gt;P&lt;/li&gt;
&lt;li&gt;T&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What people think is two pieces of data, the LLM model views it as five. &lt;/p&gt;

&lt;p&gt;When communicating code with ChatGPT, you have a smaller token budget than you do with text, meaning that you have to be more careful when inputting queries so that you don’t waste energy computing information that doesn’t matter. &lt;/p&gt;

&lt;p&gt;In this case, you want to look for the interesting parts of the source code and only send those. Some examples might be inputting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The metadata for the part of a file where your company’s name is mentioned&lt;/li&gt;
&lt;li&gt;Specific project name, location, and developer&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Lessons Learned: Engineering Prompts
&lt;/h1&gt;

&lt;p&gt;When dealing with token budgets, engineering prompts become incredibly important. Unfortunately, no clear answer around best technique exists. The process requires you to test and iterate the prompt. Some prompt improvements more than doubled the output’s value. &lt;/p&gt;

&lt;p&gt;LLMs can assume that all information provided at input is true or factual. For example, a prompt might ask a question about whether your company’s data was part of a specific data breach. The LLM will assume that the corporate data was part of the breach rather than researching the breach to look for the corporate data.&lt;/p&gt;

&lt;h1&gt;
  
  
  Future of LLMs in Cybersecurity
&lt;/h1&gt;

&lt;p&gt;A fundamental problem in cybersecurity is the communication gap across different people in the company. LLMs are powerful for communication between different audiences, especially when looking at how teams can use them for reporting. LLMs empower less experience security team members by helping them understand context so that they know how to efficiently escalate alerts. Additionally, CISOs and others interacting with business leadership can use LLMs to explain technical bugs or data breach information in a way that addresses that audience’s needs. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Working around Vue 2's lack of types using Vue Property Decorator</title>
      <dc:creator>Maxime Goyette</dc:creator>
      <pubDate>Mon, 03 Oct 2022 19:25:21 +0000</pubDate>
      <link>https://forem.com/flare/working-around-vue-2s-lack-of-types-using-vue-property-decorator-24e5</link>
      <guid>https://forem.com/flare/working-around-vue-2s-lack-of-types-using-vue-property-decorator-24e5</guid>
      <description>&lt;p&gt;Vue 2 is not type-friendly. Vue Class Component and Vue Property Decorator are libraries that help improve this, but there is still a disconnect in templates when passing properties to components.&lt;/p&gt;

&lt;p&gt;Take, for example, the following Vue component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;// SimpleCounter.vue

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimpleCounter&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Vue&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;step&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="nx"&gt;startAt&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;created&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startAt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;step&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the following parent component (notice the error!):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;// App.vue

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- There should be an error here, "potato" isn't a number! --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;simple-counter&lt;/span&gt; &lt;span class="na"&gt;step=&lt;/span&gt;&lt;span class="s"&gt;"potato"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vue 2 wouldn't have a way to prevent this error at compile time.&lt;/p&gt;

&lt;p&gt;At Flare, we have been working around this for a while by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Declaring an interface associated with every component, defining the required properties.&lt;/li&gt;
&lt;li&gt;Using computed properties to have type-checking on the interface.&lt;/li&gt;
&lt;li&gt;Passing the properties to the component using the v-bind directive.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// SimpleCounter.ts&lt;/span&gt;
&lt;span class="c1"&gt;// This file exports an interface that is used by all Simplecounter users.&lt;/span&gt;
&lt;span class="c1"&gt;// The interface has to be defined by hand, but at least it allows for&lt;/span&gt;
&lt;span class="c1"&gt;// validating that all users of the component are updated when we update&lt;/span&gt;
&lt;span class="c1"&gt;// the interface.&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;SimpleCounterProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;step&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;startAt&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;// App.vue

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;simple-counter&lt;/span&gt; &lt;span class="na"&gt;v-bind=&lt;/span&gt;&lt;span class="s"&gt;"simpleCounterProps"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Vue&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;simpleCounterProps&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;SimpleCounterProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// We couldn’t make a mistake here.&lt;/span&gt;
    &lt;span class="c1"&gt;// Typescript would warn us.&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, this isn't ideal because you have to declare the interface manually and there can be a discrepancy between the interface and the actual component. Developers modifying the component could potentially forget to update the interface and this would most likely cause bugs.&lt;/p&gt;

&lt;p&gt;The solution would be to &lt;del&gt;use Vue 3&lt;/del&gt; have a single source of truth by deriving the interface directly from the component itself. This could be done in the form of a generic utility type that takes in the class of the component and outputs an interface for its properties: &lt;code&gt;PropsOf&amp;lt;SimpleCounter&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The library &lt;code&gt;Vue Property Decorators&lt;/code&gt; has this &lt;code&gt;Prop&lt;/code&gt; decorator that automagically assigns class attributes as props. It's also possible to set default values to props using the following syntax: &lt;code&gt;@Prop({ default: 'hey' })&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This allows us to have strictly defined (as opposed to optional) attributes from an internally in the component and still accept optional properties from the parent component.&lt;/p&gt;

&lt;p&gt;We had the idea of using the class inferred interface to type the properties, but we get a bunch of Vue internals as properties such as &lt;code&gt;$refs&lt;/code&gt; and &lt;code&gt;$slots&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;A good way to get rid of these is to omit the keys of &lt;code&gt;Vue&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;This is slightly better, but we still get all of the component functions in the auto-completion, which is bad. What if it were possible to define the props and the functions separately? Let's try it!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;// SimpleCounter.vue

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimpleCounterProps&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Vue&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;step&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimpleCounter&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;SimpleCounterProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

 &lt;span class="nf"&gt;created&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;

 &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;step&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We now have a simple way to get an interface for the only the properties, or do we? Well yes, kind of, but also no, not really. The types are not fully accurate yet.&lt;/p&gt;

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

&lt;p&gt;As we can see, &lt;code&gt;step&lt;/code&gt; is correctly typed, but &lt;code&gt;start&lt;/code&gt; is not defined as an optional property. What we're looking for here is to have &lt;code&gt;start?&lt;/code&gt; instead of simply &lt;code&gt;start&lt;/code&gt; . We can do this by splitting the properties declaration into two different classes. The first class would contain the required properties and the second class would contain the optional properties.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;// SimpleCounter.vue

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimpleCounterRequiredProps&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Vue&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;step&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimpleCounterOptionalProps&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Vue&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimpleCounter&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Mixins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;RequiredProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OptionalProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

 &lt;span class="nf"&gt;created&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;

 &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;step&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes it easy to derive the correct types using a custom utility type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// utilities.ts&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PropsOf&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RequiredProps&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OptionalProps&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Vue&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Omit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Required&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RequiredProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;OptionalProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;Vue&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, let's export the derived interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;// SimpleCounter.vue
// ...
export type SimpleCounterProps = PropsOf&lt;span class="nt"&gt;&amp;lt;SimpleCounterRequiredProps&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;SimpleCounterOptionalProps&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;;
// ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can import the property types in other components and we get exactly what we were looking for:&lt;/p&gt;

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

&lt;p&gt;🎉🎉🎉&lt;/p&gt;

&lt;p&gt;I would have really liked to be able to use the &lt;code&gt;PropsOf&amp;lt;SimpleCounter&amp;gt;&lt;/code&gt; type with a single parameter, but I haven't found a way to achieve this yet.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Typing your way into safety</title>
      <dc:creator>Israël Hallé</dc:creator>
      <pubDate>Thu, 21 Jul 2022 21:06:00 +0000</pubDate>
      <link>https://forem.com/flare/typing-your-way-into-safety-4lek</link>
      <guid>https://forem.com/flare/typing-your-way-into-safety-4lek</guid>
      <description>&lt;p&gt;I've been working with Python typing annotation in the last few years as part of our main product at Flare Systems. I've found it to be a wonderful tool to support refactoring and make the code more readable. Lately, I explored how we can make API safer with the uses of types. I will specifically look about how we can use Python typing annotation to make &lt;code&gt;os.system&lt;/code&gt; foolproof.&lt;/p&gt;

&lt;p&gt;As a starting point, the current type of &lt;code&gt;system&lt;/code&gt; is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;StrOrBytesPath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This typing is correct. It has the benefits of catching any call not using a string that would be bound to fail. But this doesn't check for any misuse such as passing unsanitized user input. For example, someone might want to use &lt;a href="https://imagemagick.org/index.php"&gt;ImageMagick&lt;/a&gt; to resize an image:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"convert INPUT -resize &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; OUTPUT"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Unfortunately, this simple implementation introduced a critical flaw in our application. A user could use a malicious size such as &lt;code&gt;$(echo hacked)&lt;/code&gt;. The size would then insert itself in the command and execute the following command: &lt;code&gt;convert INPUT -resize $(echo hacked) OUTPUT&lt;/code&gt;. This exact vulnerability pattern is &lt;a href="https://nvd.nist.gov/vuln/search/results?form_type=Advanced&amp;amp;results_type=overview&amp;amp;search_type=all&amp;amp;cwe_id=CWE-78&amp;amp;isCpeNameSearch=true"&gt;still very common&lt;/a&gt; to this day.&lt;/p&gt;

&lt;p&gt;The fix is as simple as the mistake. &lt;code&gt;shlex.quote&lt;/code&gt; can be used to ensure a string is used as a single string token in a command. Yet, there's no explicit check in &lt;code&gt;system&lt;/code&gt; to ensure that the command has escaped  user inputs.&lt;/p&gt;

&lt;p&gt;Fortunately, we can think of ways to improve this. First of all, we can split all types into two categories: Safe and unsafe. As seen, using user input as &lt;code&gt;system&lt;/code&gt; argument is unsafe. But, passing a literal string should be somewhat safer. At least, literals lead to predictable behavior. If you execute the &lt;code&gt;rm --no-preserve-root -rf /&lt;/code&gt; literal you can predict that it will wipe your disk.&lt;/p&gt;

&lt;p&gt;Typing annotation users might already be familiar with the &lt;code&gt;Literal&lt;/code&gt; type. As a quick reminder, the literal type allows developers to type a variable with a literal value. This is useful for functions that might take only a finite amount of known literal value. For example, &lt;code&gt;system&lt;/code&gt; could have used it this way:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"ls"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ls"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# ok
&lt;/span&gt;&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# ok
&lt;/span&gt;
&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"rm -rf"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# error!
&lt;/span&gt;&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  &lt;span class="c1"&gt;# error!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Note that in practice I usually favor &lt;code&gt;Enum&lt;/code&gt;. This usually lead to safer code since it also check the value are correct at runtime.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One nice thing with this concept is that the type checker will not allow passing a &lt;code&gt;str&lt;/code&gt; when expecting a &lt;code&gt;Literal&lt;/code&gt;. The big limitation is that &lt;code&gt;Literal&lt;/code&gt; only work on concrete literal. There's no way to set the type of a variable to take any literal of a type:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;  &lt;span class="c1"&gt;# error: Literal[...] must have at least one parameter
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In our case this is quite restrictive since we want &lt;code&gt;system&lt;/code&gt; to run any safe command. Until Python 3.10, there were no built-in ways to have a function that only takes &lt;code&gt;Literal&lt;/code&gt; arguments. That is, before Python 3.11 adds the &lt;code&gt;LiteralString&lt;/code&gt; type. &lt;code&gt;LiteralString&lt;/code&gt; allows a variable to accept only literal strings.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;LiteralString&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"convert INPUT OUTPUT"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# ok
&lt;/span&gt;&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"convert INPUT -resize &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; OUTPUT"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# error!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;At the time of publishing, Mypy define &lt;code&gt;LiteralString&lt;/code&gt; as an alias to &lt;code&gt;str&lt;/code&gt;. Thus, the latest version of Mypy with Python 3.11 won't catch any error in the snippets above and below.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It still limits us to literal values. Going back to our use case, we want to be able to pass in the size of the image. It is actually possible to make &lt;code&gt;size&lt;/code&gt; safe by sanitizing the value for shell use. These are the usual &lt;code&gt;quote&lt;/code&gt; or &lt;code&gt;escape&lt;/code&gt; function that takes user input and return strings that are safe to use. For shells, Python has the &lt;code&gt;shlex.quote&lt;/code&gt; function available. The input and output of these functions have different safeness property. It would be interesting to reflect this difference in the types:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;ShellQuotedString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NewType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ShellQuotedString"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ShellQuotedString&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here we introduce a new type that includes the safety property. Python includes the &lt;code&gt;NewType&lt;/code&gt; tool to easily create a new type from an existing one. This new type can be used wherever the base time is used, but not the other way:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;safe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ShellQuotedString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ShellQuotedString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"This string is safe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;safe&lt;/span&gt;  &lt;span class="c1"&gt;# ok
&lt;/span&gt;&lt;span class="n"&gt;safe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;unsafe&lt;/span&gt;  &lt;span class="c1"&gt;# error: Incompatible types in assignment
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now we have both kinds of safe data: Literal and quoted data. For ease of use, we can alias both to an enum:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;ShellString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LiteralString&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;ShellQuotedString&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This enum is all the safe types of command that system can execute. This ensures that a developer has to think about quoting user input before passing them to &lt;code&gt;system&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ShellString&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"convert INPUT OUTPUT"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# ok
&lt;/span&gt;&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"convert INPUT -resize {quote(size)} OUTPUT"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# error!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It's still not accepting our quoted size argument. An interesting property of &lt;code&gt;NewType&lt;/code&gt; is that any operation done on it will convert it back to the base type. For example, concatenating a &lt;code&gt;str&lt;/code&gt; to a &lt;code&gt;ShellQuotedString&lt;/code&gt; will return  a &lt;code&gt;str&lt;/code&gt;. This put the burden on the API designer to define the set of safe operation. If we want to provide operations to work on our safe strings, we have to implement them.&lt;/p&gt;

&lt;p&gt;In our case, we know that concatenating shell-safe strings will create a new shell-safe string. So we can expose this operation as the safe way to mix user input and literal values.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;shell_format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;format_string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
  &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ShellString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ShellString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ShellQuotedString&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ShellQuotedString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;format_string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;output_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/tmp/out"&lt;/span&gt;
&lt;span class="n"&gt;shell_format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;"convert INPUT --resize {} {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
  &lt;span class="n"&gt;output_path&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# ok
&lt;/span&gt;
&lt;span class="n"&gt;shell_format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;"convert INPUT --resize {} {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="n"&gt;output_path&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# error!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Note that this implementation might still leave room for security vulnerability. Using the function like &lt;code&gt;shell_format("convert -resize '{}'", size)&lt;/code&gt; would leave &lt;code&gt;size&lt;/code&gt; effectively un-quoted. It would be possible to add some more checks to ensure any &lt;code&gt;{}&lt;/code&gt; literals aren't surrounded by quotes. This is a great example of why regular strings operation might lead to unsafe behavior if applied to our new types.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now that we have all the operation and safety property we need, we can now glue everything together:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Our &lt;code&gt;system&lt;/code&gt; API is now proved to be safe. It should be catching any misuse with unsanitized values. Note that we are using here a &lt;code&gt;ShellQuotedString&lt;/code&gt; instead of a &lt;code&gt;SafeString&lt;/code&gt; type that could be reused for many other cases (SQL quoting, &lt;code&gt;html.escape&lt;/code&gt;, etc.). Our type safety is relative to the usage of it. The return value of &lt;code&gt;html.escape&lt;/code&gt; is safe to render without introducing XSS. Yet, the same value could introduce SQL injection if used as-is in a query.&lt;/p&gt;

&lt;p&gt;Adding safety to types can go beyond escaping or quoting patterns. Types can expose most implicit preconditions to static analysis. For example, an static file API that open a file from user input could define a &lt;code&gt;SafePath&lt;/code&gt; type. A function could then convert a &lt;code&gt;str&lt;/code&gt; to &lt;code&gt;SafePath&lt;/code&gt; after it checks that it's under a specific directory.&lt;/p&gt;

&lt;p&gt;We have seen that we can easily use types to embed semantic in our code. Python typing annotation can do much more than just preventing &lt;code&gt;TypeError&lt;/code&gt;. It can make precondition explicit and prevent critical security vulnerabilities.&lt;/p&gt;

</description>
      <category>python</category>
      <category>mypy</category>
      <category>security</category>
    </item>
    <item>
      <title>Connect services across Kubernetes clusters using Teleproxy</title>
      <dc:creator>Alexandre Viau</dc:creator>
      <pubDate>Thu, 21 Jul 2022 20:36:00 +0000</pubDate>
      <link>https://forem.com/flare/connect-services-across-kubernetes-clusters-using-teleproxy-jla</link>
      <guid>https://forem.com/flare/connect-services-across-kubernetes-clusters-using-teleproxy-jla</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/flared/teleproxy" rel="noopener noreferrer"&gt;Teleproxy&lt;/a&gt; is a shell script that lets you quickly replace a Kubernetes deployment by a single pod that forwards incoming traffic to another pod running in a destination Kubernetes cluster.&lt;/p&gt;

&lt;p&gt;The tool is based on &lt;a href="https://github.com/telepresenceio/telepresence" rel="noopener noreferrer"&gt;telepresence&lt;/a&gt;. It is used at Flare Systems to keep our development setup light and still be able to quickly connect our test apps to a more realistic “staging” environment.&lt;/p&gt;

&lt;p&gt;See the code at &lt;a href="https://github.com/flared/teleproxy" rel="noopener noreferrer"&gt;https://github.com/flared/teleproxy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ideal for minimal Minikube setups&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most of Flare Systems’ development setup is based around Minikube, a tool that lets you run Kubernetes locally as a single-node cluster.&lt;/p&gt;

&lt;p&gt;While Minikube is great, we quickly ran into performance issues. Devs don’t necessarily have the resources to run all the services they need to test the software component they are working on, or maybe they’d rather have more than 30 minutes of battery life! They may also want to interface with a database that contains more data than the one that we ship in the local development environment.&lt;/p&gt;

&lt;p&gt;It would be great if there was a tool that allowed you to quickly swap the database that runs locally inside Minikube with a proxy that points to a database running in another cluster. This would allow for all services running in Minikube to instantly connect with another database with little to no configuration changes. This is exactly what teleproxy allows you to do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using teleproxy to swap a kubernetes deployment with a proxy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Say you have local deployment called &lt;code&gt;someservice&lt;/code&gt; with pods listening to port &lt;code&gt;8080&lt;/code&gt; running in your local cluster and you want to replace it with a proxy to another deployment running in a destination cluster, you would run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tele-proxy &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--source_context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;minikube &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--source_deployment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;someservice &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--source_port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8080 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--target_context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;staging &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--target_pod&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;someservice-77697866c6-vsk59 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--target_port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How it works&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Teleproxy is based on telepresence. All it does is it runs &lt;code&gt;kubectl port-forward&lt;/code&gt; in telepresence’s replacement pod. If you don’t already know how telepresence works, the following deployment diagram should help. It follows traffic from a client pod, which uses the service that we are replacing, to the target pod, which is an equivalent pod running inside another cluster.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The traffic originates from the client, it probably targets &lt;code&gt;someservice&lt;/code&gt; using the deployment's Kubernetes service.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The traffic is received by telepresence’s incluster container. Telepresence has scaled down the &lt;code&gt;someservice&lt;/code&gt; deployment and has replaced the pods by this single incluster proxy. It forwards any incoming traffic to the telepresence local pod which is running outside of the cluster.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The traffic is received by telepresence’s local container, which forwards it to the teleproxy container.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The traffic is received by teleproxy and is forwarded to the destination pod in Cluster B trough &lt;code&gt;kubectl port-forward&lt;/code&gt;. This container is able to run a port-forward to your destination cluster because it mounts your local kubectl config, some specific environment variable and contains common tools for authenticating against a kubernetes cluster such as the AWS and Google Cloud CLIs.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Debugging Teleproxy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you start from a working telepresence setup, the only complexity that is added by teleproxy is that the teleproxy container must be able to connect to your target cluster. Depending on how you regularly connect to that cluster, you may need to mount configuration files or add environment variables to the teleproxy container.&lt;/p&gt;

&lt;p&gt;We have configured teleproxy for our own use and have gotten it working with both GKE and AWS EKS, this required:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mounting &lt;code&gt;~/.aws&lt;/code&gt; , &lt;code&gt;~/.kube&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Installing the AWS CLI and Google Cloud CLI&lt;/li&gt;
&lt;li&gt;Setting up compat symlinks for OSX users.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is probably more to do, and we are willing to merge anything that makes sense.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Appendix&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Telepresence: &lt;a href="https://www.telepresence.io/discussion/overview" rel="noopener noreferrer"&gt;https://www.telepresence.io/discussion/overview&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Open Source @ Flare Systems: &lt;a href="https://flared.github.io/" rel="noopener noreferrer"&gt;https://flared.github.io/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Teleproxy: &lt;a href="https://github.com/Flared/teleproxy" rel="noopener noreferrer"&gt;https://github.com/Flared/teleproxy&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
