Securing Your Machine Identities Means Better Secrets Management

In 2024, GitGuardian released the State of Secrets Sprawl report. The findings speak for themselves; with over 12.7 million secrets detected in GitHub public repos, it is clear that hard-coded plaintext credentials are a serious problem. Worse yet, it is a growing problem, year over year, with 10 million found the previous year and 6 million found the year before that. These are not cumulative findings!

When we dig a little deeper into these numbers, one overwhelming fact springs out: specific secrets detected, the vast majority of which are API keys, outnumber generic secrets detected in our findings by a significant margin. This makes sense when you realize that API keys are used to authenticate specific services, devices, and workloads within our applications and pipelines to enable machine-to-machine communication. This is very much in line with research from CyberArk, machine identities outnumber human identities by a factor of 45 to one. This gap is only going to widen continually as we integrate more and more services in our codebases and with ever-increasing velocity.

How To Build an AI Knowledge Base With RAG

Large Language Models are immensely powerful and can quickly generate intelligent and natural-sounding responses. Their major problem, however, is a limitation of training data – GPT-4, for instance, has a knowledge cutoff date in September 2021. This means that the model is unaware of any events or developments after this date. LLMs also have consistent troubles with the accuracy of information and “hallucinations” – coherent and logical, but factually incorrect responses. Finally, LLMs are unaware of specific, niche information, and can only generate responses on a certain level of generality. 

To solve these issues and make the LLM usable for specific and information-heavy tasks, LLMs can be connected to AI knowledge bases – repositories of information that consist of organized data – product documentation, articles, messages, and other materials. In this article, I explain how to create a knowledge base that would later be connected to the LLM model and enable it to generate factually correct and specific responses. 

Cache Wisely: How You Can Prevent Distributed System Failures

Caching is often implemented as a generic solution when we think about improving the latency and availability characteristics of dependency service calls. Latency improves as we avoid the need to make the network round trip to the dependency service, and availability improves as we don’t need to worry about temporary downtimes of the dependency service given that the cache serves the required response that we are looking for. It is important to note that caching does not help if our requests to a dependency service lead to a distinct response every time, or if a client makes vastly different request types with not much overlap between responses. There are also additional constraints to using caching if our service cannot tolerate stale data. 

We won’t be delving into caching types, techniques, and applicability as those are covered broadly on the internet. Instead, we will focus on the less talked about risk with caching that gets ignored as systems evolve, and this puts the system at risk of a broad outage. 

“If” CSS Gets Inline Conditionals

A few sirens went off a couple of weeks ago when the CSS Working Group (CSSWG) resolved to add an if() conditional to the CSS Values Module Level 5 specification. It was Lea Verou’s X post that same day that caught my attention:

Lea is the one who opened the GitHub issue leading to the discussion and in a stroke of coincidence — or serendipity, perhaps — the resolution came in on her birthday. That had to be quite a whirlwind of a day! What did you get for your birthday? “Oh, you know, just an accepted proposal to the CSS spec.” Wild, just wild.

The accepted proposal is a green light for the CSSWG to work on the idea with the intent of circulating a draft specification for further input and considerations en route to, hopefully, become a recommended CSS feature. So, it’s gonna be a hot minute before any of this is baked, that is, if it gets fully baked.

But the idea of applying styles based on a conditional requirement is super exciting and worth an early look at the idea. I scribbled some notes about it on my blog the same day Lea posted to X and thought I’d distill those here for posterity while rounding up more details that have come up since then.

This isn’t a new idea

Many proposals are born from previously rejected proposals and if() is no different. And, indeed, we have gained several CSS features in recent days that allow for conditional styling — :has() and Container Style Queries being two of the more obvious examples. Lea even cites a 2018 ticket that looks and reads a lot like the accepted proposal.

The difference?

Style queries had already shipped, and we could simply reference the same syntax for conditions (plus media() and supports() from Tab’s @when proposal) whereas in the 2018 proposal how conditions would work was largely undefined.

Lea Verou, “Inline conditionals in CSS?”

I like how Lea points out that CSS goes on to describe how CSS has always been a conditional language:

Folks… CSS had conditionals from the very beginning. Every selector is essentially a conditional!

Lea Verou, “Inline conditionals in CSS?”

True! The Cascade is the vehicle for evaluating selectors and matching them to HTML elements on a page. What if() brings to the table is a way to write inline conditions with selectors.

Syntax

It boils down to this:

<if()> = if( <container-query>, [<declaration-value>]{1, 2} )

…where:

  • Values can be nested to produce multiple branches.
  • If a third argument is not provided, it becomes equivalent to an empty token stream.

All of this is conceptual at the moment and nothing is set in stone. We’re likely to see things change as the CSSWG works on the feature. But as it currently stands, the idea seems to revolve around specifying a condition, and setting one of two declared styles — one as the “default” style, and one as the “updated” style when a match occurs.

.element {
  background-color:
    /* If the style declares the following custom property: */
    if(style(--variant: success),
      var(--color-green-50), /* Matched condition */
      var(--color-blue-50);  /* Default style */
    );
}

In this case, we’re looking for a style() condition where a CSS variable called --variant is declared and is set to a value of success, and:

  • …if --variant is set to success, we set the value of success to --color-green-50 which is a variable mapped to some greenish color value.
  • …if --variant is not set to success, we set the value of the success to --color-blue-50 which is a variable mapped to some bluish color value.

The default style would be optional, so I think it can be omitted in some cases for slightly better legibility:

.element {
  background-color:
    /* If the style declares the following custom property: */
    if(style(--variant: success),
      var(--color-green-50) /* Matched condition */
    );
}

The syntax definition up top mentions that we could support a third argument in addition to the matched condition and default style that allows us to nest conditions within conditions:

background-color: if(
  style(--variant: success), var(--color-success-60), 
    if(style(--variant: warning), var(--color-warning-60), 
      if(style(--variant: danger), var(--color-danger-60), 
        if(style(--variant: primary), var(--color-primary)
      )
    ),
  )
);

Oomph, looks like some wild inception is happening in there! Lea goes on to suggest a syntax that would result in a much flatter structure:

<if()> = if( 
  [ <container-query>, [<declaration-value>]{2}  ]#{0, },
  <container-query>, [<declaration-value>]{1, 2} 
)

In other words, nested conditions are much more flat as they can be declared outside of the initial condition. Same concept as before, but a different syntax:

background-color: if(
  style(--variant: success), var(--color-success-60), 
  style(--variant: warning), var(--color-warning-60),
  style(--variant: danger), var(--color-danger-60), 
  style(--variant: primary), var(--color-primary)
);

So, rather than one if() statement inside another if() statement, we can lump all of the possible matching conditions into a single statement.

We’re attempting to match an if() condition by querying an element’s styles. There is no corresponding size() function for querying dimensions — container queries implicitly assume size:

.element {
  background: var(--color-primary);

  /* Condition */
  @container parent (width >= 60ch) {
    /* Applied styles */
    background: var(--color-success-60);
  }
}

And container queries become style queries when we call the style() function instead:

.element {
  background: orangered;

  /* Condition */
  @container parent style(--variant: success) {
    /* Applied styles */
    background: dodgerblue;
  }
}

Style queries make a lot more sense to me when they’re viewed in the context of if(). Without if(), it’s easy to question the general usefulness of style queries. But in this light, it’s clear that style queries are part of a much bigger picture that goes beyond container queries alone.

There’s still plenty of things to suss out with the if() syntax. For example, Tab Atkins describes a possible scenario that could lead to confusion between what is the matched condition and default style parameters. So, who knows how this all shakes out in the end!

Conditions supporting other conditions

As we’ve already noted, if() is far from the only type of conditional check already provided in CSS. What would it look like to write an inline conditional statement that checks for other conditions, such as @supports and @media?

In code:

background-color: if(
  supports( /* etc. */ ),
  @media( /* etc. */ )
);

The challenge would be container supporting size queries. As mentioned earlier, there is no explicit size() function; instead it’s more like an anonymous function.

@andruud has a succinctly describes the challenge in the GitHub discussion:

I don’t see why we couldn’t do supports() and media(), but size queries would cause cycles with layout that are hard/impossible to even detect. (That’s why we needed the restrictions we currently have for size CQs in the first place.

“Can’t we already do this with [X] approach?”

When we were looking at the syntax earlier, you may have noticed that if() is just as much about custom properties as it is about conditionals. Several workarounds have emerged over the years to mimic what we’d gain if() we could set a custom property value conditionally, including:

  • Using custom properties as a Boolean to apply styles or not depending on whether it is equal to 0 or 1. (Ana has a wonderful article on this.)
  • Using a placeholder custom property with an empty value that’s set when another custom property is set, i.e. “the custom property toggle trick” as Chris describes it.
  • Container Style Queries! The problem (besides lack of implementation) is that containers only apply styles to their descendants, i.e., they cannot apply styles to themselves when they meet a certain condition, only its contents.

Lea gets deep into this in a separate post titled “Inline conditional statements in CSS, now?” that includes a table that outlines and compares approaches, which I’ll simply paste below. The explanations are full of complex CSS nerdery but are extremely helpful for understanding the need for if() and how it compares to the clever “hacks” we’ve used for years.

MethodInput valuesOutput valuesProsCons
Binary Linear InterpolationNumbersQuantitativeCan be used as part of a valueLimited output range
Togglesvar(--alias) (actual values are too weird to expose raw)AnyCan be used in part of a valueWeird values that need to be aliased
Paused animationsNumbersAnyNormal, decoupled declarationsTakes over animation property

Cascade weirdness
Type GrindingKeywordsAny value supported by the syntax descriptorHigh flexibility for exposed APIGood encapsulationMust insert CSS into light DOM

Tedious code (though can be automated with build tools)

No Firefox support (though that’s changing)
Variable animation nameKeywordsAnyNormal, decoupled declarationsImpractical outside of Shadow DOM due to name clashes

Takes over animation property

Cascade weirdness

Happy birthday, Lea!

Belated by two weeks, but thanks for sharing the spoils of your big day with us! 🎂

References

To Shared LinkPermalink on CSS-Tricks


“If” CSS Gets Inline Conditionals originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

Pure Storage Empowers Developers and Data Scientists With Agile, High-Performance Storage for AI and Modern Applications

In the rapidly evolving world of artificial intelligence (AI) and modern application development, agility and high-performance storage are crucial for success. Pure Storage, with its innovative solutions like FlashBlade and Evergreen//One for AI, is empowering developers and data scientists to accelerate their workloads and drive business value.

Architecting FlashBlade for Predictable AI Performance at Scale

AI and machine learning (ML) workloads demand storage that can deliver consistent, high-bandwidth performance at scale. FlashBlade, Pure Storage's unified fast file and object storage solution, is uniquely architected to meet these challenges head-on.

How to uploade the .gzip file to Swift Object Store?

I wrote the Python code to upload the .gz file from my local machine to the OpenStack object store using the following documentation: https://docs.openstack.org/python-swiftclient/latest/client-api.html.
Below is the code I wrote.

from keystoneauth1 import session
    from keystoneauth1.identity import v3
    from swiftclient.client import Connection, logger
    from swiftclient.client import ClientException
    import gzip

    # Create a password auth plugin
    auth = v3.Password(
        auth_url='https://cloud.company.com:5000/v3/',
        username='myaccount',
        password='mypassword',
        user_domain_name='Default',
        project_name='myproject',
        project_domain_name='Default'
    )

    # Create swiftclient Connection
    swift_conn = Connection(session=keystone_session)

    # Create a new container
    container = 'object-backups'
    swift_conn.put_container(container)
    res_headers, containers = swift_conn.get_account()
    if container in containers:
        print("The container " + container + " was created!")

    # Create a new object with the contents of Netbox database backup
    with gzip.open('/var/backup/netbox_backups/netbox_2024-03-16.psql.gz', 'rb') as f:
        # Read the contents...
        file_gz_content = f.read()

        # Upload the returned contents to the Swift Object Storage container
        swift_conn.put_object(
            container,
            "object_netbox_2024-06-16.psql.gz",
            contents=file_gz_content,
            content_type='application/gzip'
        )

    # Confirm the presence of the object holding the Netbox database backup
    obj1 = 'object_netbox_2024-06-16.psql.gz'
    container = 'object-backups'
    try:
        resp_headers = swift_conn.head_object(container, obj1)
        print("The object " + obj1 + " was successfully created")
    except ClientException as e:
        if e.http_status == '404':
            print("The object " + obj1 + " was not found!")
        else:
            print("An error occurred checking for the existence of the object " + obj1)

The file gets uploaded successfully. However, if I download the file from the object store and try to decompress it, I get the following error:

# gzip -d object_netbox_2024-06-16.psql.gz 

gzip: sanbox_nb01_netbox_2024-06-16.psql.gz: not in gzip format

What should I do to ensure the file gets downloaded in the same format and size to the Object storage as the file in my local machine?

Any assistance will be appreciated.

Yours sincerely

Master AWS IAM Role Configuration With Terraform

It's super important today to keep things secure and make sure everything is running as it should. AWS Identity and Access Management (IAM) helps with this by letting you manage who can get into what parts of your AWS account. One cool thing about IAM is that it lets you give permissions to different parts or people in your account without having to share sensitive info like passwords. Today, I'm going to talk about using Terraform, a tool that lets you set up infrastructure through code, to create and set up these IAM roles easily.

Understanding AWS IAM Roles and Terraform

Before we get into how to use Terraform for setting up IAM roles in AWS, it's key to grasp what AWS IAM roles and Terraform are all about. In your AWS account, you can create IAM roles, which are basically identities with certain permissions attached. These roles let you give specific rights to different parts of your AWS setup without any hassle. On the flip side, Terraform is a tool that lets you manage your infrastructure through code instead of doing everything manually. It’s made specifically for working smoothly with services such as those offered by AWS, thanks to the Terraform AWS provider.

Maven Archetypes: Simplifying Project Template Creation

With Maven Archetypes, you can create a template for your Maven projects. It is a great way to enable and apply best practices within your project or organization. In this blog, you will learn how to create archetypes from scratch and based on an existing project. Enjoy!

Introduction

Maven Archetypes serve as templates for creating Maven projects. Often, you will have some best practices for your organization or team on how to create Maven projects. You can describe these on an intranet or Confluence, but it is even better to create templates for it. And that is what Maven Archetypes can do for you. You can create templates from scratch or you can create a project first and generate a template from the project. And even more, it is not very complicated. So let’s get started and see how this works!

This Is How SSL Certificates Work: HTTPS Explained in 15 Minutes

The world of online security may seem complex, but understanding the basics of how SSL certificates work and why HTTPS is essential can empower you to make safer choices online. Just like Jane, you can navigate the digital landscape with confidence, knowing that your data is protected from prying eyes. So next time you browse the web, remember the story of Jane and the coffee shop hacker and choose secure, trusted websites for your online activities. Let’s start our day with Jane who was enjoying her coffee peacefully.

Chapter 1: The Coffee Shop Conundrum

It was a sunny afternoon, and Jane decided to take a break from her hectic day. She headed to her favorite coffee shop, ordered a latte, and found a cozy corner to catch up on some online shopping and emails. As she settled in, she connected her laptop to the coffee shop’s free Wi-Fi and began browsing. Little did she know, a hacker named Bob was sitting just a few tables away, eager to intercept her data.