Recruiting on ability and potential

Let’s not just hire people who look and think and talk (and take exams) like us

This is one of those more open-ended posts, in that I don’t have any good answers, but I’ve got a bunch of questions. I’d love to have feedback, comments and thoughts if you have any.

This week, it turns out is “results week” in the UK. Here, there are two major sets of exams which most students take: GCSEs and A levels. The former generally are taken by 16 year olds, with around 8-12 in total, and the latter by 18 year olds, with 2-4 in total (3 being the strong median). A level results are one of the major criteria for entry into universities, and GCSE results typically determine what A levels students will take, and therefore have an impact on university course choice in the future. In normal years, A level results are release a week before the GCSE results, but (Covid having messed things up), A level results day is Tuesday, 2021-08-10, and GCSE results day is Thursday, 2021-08-12.

Both GCSEs and A levels are determined, in most cases, mainly by examination, with even subjects like PE (Physical Education), Dance and Food Technology having fairly large examination loads. This was not always the case, particularly for GCSEs, which, when they were launched in the mid 1980s, had much larger coursework components than now, aiming to provide opportunities to those who may have learned retained lots of information, but for whom examinations are not a good way of showing their expertise or acquired knowledge base.

At this point, I need to come out with an admission: exams suit me just fine. I’ve always been able to extricate information from my memory in these sorts of situations and put it down on paper, whether that’s in a school setting, university setting or professional setting (I took the CISSP examination ages ago). But this isn’t true for everybody. Exams are very artificial situations, and they just don’t work for many people. The same is true for other types of attempts to extract information out of people, such as classic coding tests. Now, I know that coding tests, when designed and applied well, can do a good job in finding out how people think, as well as what they know – in fact, that should be true for many well-designed examinations – but not only are they not always well administered, but the very context in which they are taken can severely disadvantage folks whose preferred mechanism of coding is more solitary and interactive than performative.

A family friend, currently applying for university places, expressed surprise the other day that some of the Computer Science courses for which he was applying didn’t require any previous experience of programming. I reflected that for some candidates, access to computing resources might be very limited, putting them at a disadvantage. I’ve made a similar argument when discussing how to improve diversity in security (see Is homogeneity bad for security?): we mustn’t make assumptions about people’s potential based on their previous ability to access resources which would allow that ability to be expressed and visible.

What does this have to do with recruitment, particularly? Everything. I’ve been involved in recruiting some folks recently, and the more I think about it, the more complex I realise the task is. Finding the right people – the people who will grow into roles, and become really strong players – is really tricky. I’m not just talking about finding candidates and encouraging them to apply (both difficult tasks in their own rights), but choosing from the candidates that do apply. I don’t want to just people who examine well (looking solely at their academic grades), people who perform well (who shine at coding exercises), people who interview well (those who are confident in face-to-face or video conference settings). I want to find people who have the ability to work in a team, grow the projects they’re working on, contribute creatively to what they’re doing. That may include people who fall apart in exams, who freeze during coding exercises, or whose social anxiety leads them to interview “badly”.

I’m not sure how to address these problems completely, but there are some things we can try. Here are my thoughts, and I’d love to hear more:

  1. Look beyond exams, and rate experience equally with academic attainment
  2. Accommodate different working styles
  3. Be aware that the candidate may not share your preferred interaction style
  4. Think “first language” and work with those whose native language is not yours
  5. Look beyond the neurotypical

None of these is rocket science, and I hope that the recent changes in working habits brought around by the Covid pandemic have already started people thinking about these issues, but let’s work harder to find the right people – not just the people who look and think and talk (and take exams) just like us.

In praise of … the Community Manager

I am not – and could never be – a community manager

This is my first post in a while. Since Hanging up my Red Hat I’ve been busy doing … stuff. Stuff which I hope to be able to speak about soon. But in the meantime, I wanted to start blogging regularly again. Here’s my first post back, a celebration of an important role associated with open source projects: the community manager.

Open source communities don’t just happen. They require work. Sometimes the technical interest in an open source project is enough to attract a group of people to get involved, but after some time, things are going to get too big for those with a particular bent (documentation, coding, testing) to manage the interactions between the various participants, moderate awkward (or downright aggressive) communications, help encourage new members to contribute, raise the visibility of the project into new areas or market sectors and all the other pieces that go into keeping a project healthy.

Enter the Community Manager. The typical community manager is in that awkward position of having lots of responsibility, but no direct authority. Open source projects being what they are, few of them have empowered “officers”, and even when there are governance structures, they tend to operate by consent of those involved – by negotiated, rather than direct, authority. That said, by the point a community manager is appointed for a community manager, it’s likely that at least one commercial entity is sufficiently deep into the project to fund or part-fund the community manager position. This means that the community manager will hopefully have some support from at least one set of contributors, but will still need to build consensus across the rest of the community. There may also be tricky times, also, when the community manager will need to decide whether their loyalties lie with their employer or with the community. A wise employer should set expectations about how to deal with such situations before they arise!

What does the community manager need to do, then? The answer to this will depend on a number of issues, and there is likely to be a balance between these tasks, but here’s a list of some that come to mind[1].

  • marketing/outreach – this is about raising visibility of the project, either in areas where it is already known, or new markets/sectors, but there are lots of sub-tasks such as a branding, swag ordering (and distribution!), analyst and press relations.
  • event management – setting up meetups, hackathons, booths at larger events or, for really big projects, organising conferences.
  • community growth – spotting areas where the project could use more help (docs, testing, outreach, coding, diverse and inclusive representation, etc.) and finding ways to recruit contributors to help improve the project.
  • community lubrication – this is about finding ways to keep community members talking to each other, celebrate successes, mourn losses and generally keep conversations civil at least and enthusiastically friendly at best.
  • project strategy – there are times in a project when new pastures may beckon (a new piece of functionality might make the project exciting to the healthcare or the academic astronomy community for instance), and the community manager needs to recognise such opportunities, present them to the community, and help the community steer a path.
  • product management – in conjunction with project strategy, situations are likely to occur when a set of features or functionality are presented to the community which require decisions about their priority or the ability of the community to resource them. These may even create tensions between various parts of the community, including involved commercial interests. The community manager needs to help the community reason about how to make choices, and may even be called upon to lead the decision-making process.
  • partner management – as a project grows, partners (open source projects, academic institutions, charities, industry consortia, government departments or commercial organisations) may wish to be associated with the project. Managing expectations, understanding the benefits (or dangers) and relative value can be a complex and time-consuming task, and the community manager is likely to be the first person involved.
  • documentation management – while documentation is only one part of a project, it can often be overlooked by the core code contributors. It is, however, a vital resource when considering many of the tasks associated with the points above. Managing strategy, working with partners, creating press releases: all of these need good documentation, and while it’s unlikely that the community manager will need to write it (well, hopefully not all of it!), making sure that it’s there is likely to be their responsibility.
  • developer enablement – this is providing resources (including, but not restricted to, documentation) to help developers (particularly those new to the project) to get involved in the project. It is often considered a good idea to separate this set of tasks out, rather than expecting a separate role to that of a community manager, partly because it may require a deeper technical focus than is required for many of the other responsibilities associated with the role. This is probably sensible, but the community manager is likely to want to ensure that developer enablement is well-managed, as without new developers, almost any project will eventually calcify and die.
  • cat herding – programmers (who make up the core of any project) are notoriously difficult to manage. Working with them – particularly encouraging them to work to a specific set of goals – has been likened to herding cats. If you can’t herd cats, you’re likely to struggle as a community manager!

Nobody (well almost nobody) is going to be an expert in all of these sets of tasks, and many projects won’t need all of them at the same time. Two of the attributes of a well-established community manager are an awareness of the gaps in their expertise and a network of contacts who they can call on for advice or services to fill out those gaps.

I am not – and could never be – a community manager. I don’t have the skills (or the patience), and one of the joys of gaining experience and expertise in the world is realising when others do have skills that you lack, and being able to recognise and celebrate what they can bring to your world that you can’t. So thank you, community managers!


1 – as always, I welcome comments and suggestions for how to improve or extend this list.

Hanging up my Red Hat

It’s time to move on.

Friday (2021-06-11) was my last day at Red Hat. I’ve changed my LinkedIn, Facebook and Twitter profiles and updated the information on this blog, too. I’d been at Red Hat for just under 5 years, which is one of the longest stays I’ve had at any company in my career. When I started there, I realised that there was a huge amount about the company which really suited who I was, and my attitude to life, and, in particular, open source. That hasn’t changed, and although the company is very different to the one I joined in 2016 – it’s been acquired by IBM, got a new CEO and more than doubled in size – there’s still lots about it which feels very familiar and positive. Bright people, doing stuff they care about, and sharing what they’re doing with the rest of the company and the world: great values.

I’ve also made lots of friends, and got involved in lots of cool things and institutions. I’d particularly call out Opensource.com and the Confidential Computing Consortium. And, of course, the Enarx project.

But … it’s time to move on. I’ve developed an interest in something I care a whole lot about, and which, after lots of discussion and soul-searching, I’ve decided to move into that. I hope to be able to talk more about it in a few weeks, and until then, this blog may be a little quiet. In the meantime, have fun, keep safe and do all that good security stuff.

Data may be neutral: information is not

We tend to think of data as, well, binary

Bias – particularly unintentional bias – is interesting, as I’ve noted before in my article Trust you? I can’t trust myself. The Guardian published an interesting report recently on bias in the field of digital forensics which is not, as you might expect, a discussion on algorithmic bias AI/ML (a problem which is a major concern in criminal profiling and even sentencing), but actually about the people performing digital forensics.

The story is based on a (“soon to be published”) study which basically found that, presented with the same data set (a hard drive, presumably with logging and system information on it), digital forensics researchers were more likely to find incriminating information on it when they were told that the drive’s owner had already confessed or was likely to be guilty than if they were considered innocent.

This sounds horrifying and, on first consideration, very surprising, but if the raw data put in front of people were a police interview transcript, I think that many of us would be less surprised by such a result. We know that we read words and sentences differently based on our assumptions and biases (just look at research on candidate success for CVs/resumes where the name of the candidate is clearly male versus female, or suggests a particular ethnic group or religious affiliation), and we are even familiar scientific evidence being debated by experts in court. So why are we surprised by the same result when considering data on a hard drive?

I think the answer is that we tend to think of data as, well, binary: it’s either one thing or it’s not. That’s true, of course (quantum effects aside), but data still needs to be found, considered and put into context in order to be useful: it needs to be turned into information. Hopefully, an AI/ML system applied to the same data multiple times would extract the same information but, as noted above, we can’t be sure that there’s no bias inherent in the AI/ML model already. The process of informationising the data, if you will, moves from deterministic ones and zeroes to information via processes (“algorithms”, if you will) which are complex and provide ample opportunity for for the humans carrying them out (or training the AI/ML models which will carry them out) to introduce bias.

This means that digital forensics experts need training to try to expose their own unconscious bias(es!) in just the same way that experts in other types of evidence do. Humans bring their flaws and imperfections to every field of endeavour, and digital forensics is no different. In fact, in my view, the realisation that digital forensics, as a discipline, is messy and complex is a positive step on the way to its maturing as a field of study and taking its place in set of tools available to criminal investigators, technical auditors and beyond.

Defining the Edge

How might we differentiate Edge computing from Cloud computing?

This is an edited excerpt from my forthcoming book on Trust in Computing and the Cloud for Wiley.

There’s been a lot of talk about the Edge, and almost as many definitions as there are articles out there. As usual on this blog, my main interest is around trust and security, so this brief look at the Edge concentrates on those aspects, and particularly on how we might differentiate Edge computing from Cloud computing.

The first difference we might identify is that Edge computing addresses use cases where consolidating compute resource in a centralised location (the typical Cloud computing case) is not necessarily appropriate, and pushes some or all of the computing power out to the edges of the network, where it can computing resources can process data which is generated at the fringes, rather than having to transfer all the data over what may be low-bandwidth networks for processing. There is no generally accepted single industry definition of Edge computing, but examples might include:

  • placing video processing systems in or near a sports stadium for pre-processing to reduce the amount of raw footage that needs to be transmitted to a centralised data centre or studio
  • providing analysis and safety control systems on an ocean-based oil rig to reduce reliance and contention on an unreliable and potentially low-bandwidth network connection
  • creating an Internet of Things (IoT) gateway to process and analyse data environmental sensor units (IoT devices)
  • mobile edge computing, or multi-access edge computing (both abbreviated to MEC), where telecommunications services such as location and augmented reality (AR) applications are run on cellular base stations, rather than in the telecommunication provider’s centralised network location.

Unlike Cloud computing, where the hosting model is generally that computing resources are consumed by tenants – customers of a public cloud, for instance- in the Edge case, the consumer of computing resources is often the owner of the systems providing them (though this is not always the case). Another difference is the size of the host providing the computing resources, which may range from very large to very small (in the case of an IoT gateway, for example). One important factor about most modern Edge computing environments is that they employ the same virtualisation and orchestration techniques as the cloud, allowing more flexibility in deployment and lifecycle management over bare-metal deployments.

A table comparing the various properties typically associated with Cloud and Edge computing shows us a number of differences.


Public cloud computingPrivate cloud computingEdge computing
LocationCentralisedCentralisedDistributed
Hosting modelTenantsOwnerOwner or tenant(s)
Application typeGeneralisedGeneralisedMay be specialised
Host system sizeLargeLargeLarge to very small
Network bandwidthHighHighMedium to low
Network availabilityHighHighHigh to low
Host physical securityHighHighLow
Differences between Edge computing and public/private cloud computing

In the table, I’ve described two different types of cloud computing: public and private. The latter is sometimes characterised as on premises or on-prem computing, but the point here is that rather than deploying applications to dedicated hosts, workloads are deployed using the same virtualisation and orchestration techniques employed in the public cloud, the key difference being that the hosts and software are owned and managed by the owner of the applications. Sometimes these services are actually managed by an external party, but in this case there is a close commercial (and concomitant trust) relationship to this managed services provider, and, equally important, single tenancy is assured (assuming that security is maintained), as only applications from the owner of the service are hosted[1]. Many organisations will mix and match workloads to different cloud deployments, employing both public and private clouds (a deployment model known as hybrid cloud) and/or different public clouds (a deployment model known as multi-cloud). All these models – public computing, private computing and Edge computing – share an approach in common: in most cases, workloads are not deployed to bare-metal servers, but to virtualisation platforms.

Deployment model differences

What is special about each of the models and their offerings if we are looking at trust and security?

One characteristic that the three approaches share is scale: they all assume that hosts will have with multiple workloads per host – though the number of hosts and the actual size of the host systems is likely to be highest in the public cloud case, and lowest in the Edge case. It is this high workload density that makes public cloud computing in particular economically viable, and one of the reasons that it makes sense for organisations to deploy at least some of their workloads to public clouds, as Cloud Service Providers can employ economies of scale which allow them to schedule workloads onto their servers from multiple tenants, balancing load and bringing sets of servers in and out of commission (a computation- and time-costly exercise) infrequently. Owners and operators of private clouds, in contrast, need to ensure that they have sufficient resources available for possible maximum load at all times, and do not have the opportunities to balance loads from other tenants unless they open up their on premises deployment to other organisations, transforming themselves into Cloud Service Providers and putting them into direct competition with existing CSPs.

It is this push for high workload density which is one of the reasons for the need for strong workload-from-workload (type 1) isolation, as in order to be able to maintain high density, cloud owners need to be able to mix workloads from multiple tenants on the same host. Tenants are mutual untrusting; they are in fact likely to be completely unaware of each other, and, if the host is doing its job well, unaware of the presence of other workloads on the same host as them. More important than this property, however, is a strong assurance that their workloads will not be negatively impacted by workloads from other tenants. Although negative impact can occur in other contexts to computation – such as storage contention or network congestion – the focus is mainly on the isolation that hosts can provide.

The likelihood of malicious workloads increases with the number of tenants, but reduces significantly when the tenant is the same as the host owner – the case for private cloud deployments and some Edge deployments. Thus, the need for host-from-workload (type 2) isolation is higher for the public cloud – though the possibility of poorly written or compromised workloads means that it should not be neglected for the other types of deployment.

One final difference between the models is that for both public and private cloud deployments the physical vulnerability of hosts is generally considered to be low[2], whereas the opportunities for unauthorised physical access to Edge computing hosts are considered to be much higher. You can read a little more about the importance of hardware as part of the Trusted Compute Base in my article Turtles – and chains of trust, and it is a fundamental principle of computer security that if an attacker has physical access to a system, then the system must be considered compromised, as it is, in almost all cases, possible to compromise the confidentiality, integrity and availability of workloads executing on it.

All of the above are good reasons to apply Confidential Computing techniques not only to cloud computing, but to Edge computing as well: that’s a topic for another article.


1 – this is something of a simplification, but is a useful generalisation.

2 – Though this assumes that people with authorised access to physical machines are not malicious, a proposition which cannot be guaranteed, but for which monitoring can at least be put in place.

Masks, vaccinations, social distancing – and cybersecurity

The mappingn the realms of cybersecurity and epidemiology is not perfect, but metaphors can be useful.

Waaaaay back in 2018 (which seems a couple of decades ago now), I wrote an article called Security patching and vaccinations: a surprising link. In those days, Spectre and Meltdown were still at the front of our minds, and the impact of something like Covid-19 was, if not unimaginable, then far from what most of us considered in our day-to-day lives. In the article, I argued that patching of software and vaccination (of humans or, I guess, animals[1]) had some interesting parallels (the clue’s in the title, if I’m honest). As we explore the impact of new variants of the Covid-19 virus, the note that “a particular patch may provide resistance to multiple types of attack of the same family, as do some vaccinations” seems particularly relevant. I also pointed out that although there are typically some individuals in a human population for whom vaccination is too risky, a broad effort to vaccinate the rest of the population has positive impact for them; in a similar way to how patching most systems in a deployment can restrict the number of “jumping off points” or attack.

I thought it might be interesting to explore other similarities between disease management in the human sphere with how we do things in cybersecurity, not because they are exact matches, but because they can be useful metaphors to explain to colleagues, family and friends what we do.

Vaccinations

We’ve looked a vaccinations a bit above: the key point here is that once a vulnerability is discovered, software vendors can release patches which, if applied correctly, protect the system from those attacks. This is not dissimilar in effect to the protection provided by vaccinations in human settings, though the mechanism is very different. Computer systems don’t really have an equivalent to anti-bodies or immune systems, but patches may – like vaccines – provide protection for more than one specific attack (think virus strain) if others exploit the same type of weakness.

Infection testing

As we have discovered since the rise of Covid-19, testing of the population is a vital measure to understand what other mechanisms need to be put in place to control infection. The same goes for cybersecurity. Testing the “health” of a set of systems, monitoring their behaviour and understanding which may be compromised, by which attacks, leveraging which vulnerabilities, is a key part of any cybersecurity strategy, and easily overlooked when everything seems to be OK.

Masks

I think of masks as acting a little like firewalls, or mechanisms like SELinux which act to prevent malicious programs from accessing parts of the system which you want to protect. Like masks, these mechanisms reduce the attack surface available to bad actors by stopping up certain “holes” in the system, making it more difficult to get in. In the case of firewalls, it’s network ports, and in the case of SELinux, it’s activities like preventing unauthorised system calls (syscalls). We know that masks are not wholly effective in preventing transmission of Covid-19 – they don’t give 100% protection from oral transmission, and if someone sneezes into your eye, for instance, that could lead to infection – but we also know that if two people are meeting, and they both wear masks, the chance of transmission from an infected to an uninfected person is reduced. Most cybersecurity controls aim mainly to protect the systems on which they reside, but a well thought-out deployment may also aim to put in controls to prevent attackers from jumping from one system to another.

Social distancing

This last point leads us to our final metaphor: social distancing. Here, we put in place controls to try to make it difficult for an attacker (or virus) to jump from one system to another (or human to another). While the rise of zero trust architectures has led to something of a down-playing of some of these techniques within cybersecurity, mechanisms such as DMZs, policies such as no USB drives and, at the extreme end, air-gapping of systems (where there is no direct network connection between them) all aim to create physical or logical barriers to attacks or transmission.

Conclusion

The mapping between controls in the realms of cybersecurity and epidemiology is not perfect, but metaphors can be useful in explaining the mechanisms we use and also in considering differences (is there an equivalent of “virus load” in computer systems, for instance?). If there are lessons we can learn from the world of disease managemet, then we should be keen to do so.


1 – it turns out that you can actually vaccinate plants, too: neat.

Does my TCB look big in this?

The smaller your TCB the less there is to attack, and that’s a good thing.

This isn’t the first article I’ve written about Trusted Compute Bases (TCBs), so if the concept is new to you, I suggest that you have a look at What’s a Trusted Compute Base? to get an idea of what I’ll be talking about here. In that article, I noted the importance of the size of the TCB: “what you want is a small, easily measurable and easily auditable TCB on which you can build the rest of your system – from which you can build a ‘chain of trust’ to the other parts of your system about which you care.” In this article, I want to take some time to discuss the importance of the size of a TCB, how we might measure it, and how difficult it can be to reduce the TCB size. Let’s look at all of those issues in order.

Size does matter

However you measure it – and we’ll get to that below – the size of the TCB matters for two reasons:

  1. the larger the TCB is, the more bugs there are likely to be;
  2. the larger the TCB is, the larger the attack surface.

The first of these is true of any system, and although there may be ways of reducing the number of bugs, proving the correctness of all or, more likely, part of the system, bugs are both tricky to remove and resilient – if you remove one, you may well be introducing another (or worse, several). Now, the kinds or bugs you have, and the number of them, can be reduced through a multitude of techniques, from language choice (choosing Rust over C/C++ to reduce memory allocation errors, for instance) to better specification and on to improved test coverage and fuzzing. In the end, however, the smaller the TCB, the less code (or hardware – we’re considering the broader system here, don’t forget), you have to trust, the less space there is for there to be bugs in it.

The concept of an attack surface is important, and, like TCBs, one I’ve introduced before (in What’s an attack surface?). Like bugs, there may be no absolute measure of the ratio of danger:attack surface, but the smaller your TCB, well, the less there is to attack, and that’s a good thing. As with bug reduction, there are number of techniques you may want to apply to reduce your attack surface, but the smaller it is, then, by definition, the fewer opportunities attackers have to try to compromise your system.

Measurement

Measuring the size of your TCB is really, really hard – or, maybe I should say that coming up with an absolute measure that you can compare to other TCBs is really, really hard. The problem is that there are so many measurements that you might take. The ones you care about are probably those that can be related to attack surface – but there are so many different attack vectors that might be relevant to a TCB that there are likely to be multiple attack surfaces. Let’s look at some of the possible measurements:

  • number of API methods
  • amount of data that can be passed across each API method
  • number of parameters that can be passed across each API method
  • number of open network sockets
  • number of open local (e.g. UNIX) sockets
  • number of files read from local storage
  • number of dynamically loaded libraries
  • number of DMA (Direct Memory Access) calls
  • number of lines of code
  • amount of compilation optimisation carried out
  • size of binary
  • size of executing code in memory
  • amount of memory shared with other processes
  • use of various caches (L1, L2, etc.)
  • number of syscalls made
  • number of strings visible using strings command or similar
  • number of cryptographic operations not subject to constant time checks

This is not meant to be an exhaustive list, but just to show the range of different areas in which vulnerabilities might appear. Designing your application to reduce one may increase another – one very simple example being an attempt to reduce the number of API calls exposed by increasing the number of parameters on each call, another being to reduce the size of the binary by using more dynamically linked libraries.

This leads us to an important point which I’m not going to address in detail in this article, but which is fundamental to understanding TCBs: that without a threat model, there’s actually very little point in considering what your TCB is.

Reducing the TCB size

We’ve just seen one of the main reasons that reducing your TCB size is difficult: it’s likely to involve trade-offs between different measures. If all you’re trying to do is produce competitive marketing material where you say “my TCB is smaller than yours”, then you’re likely to miss the point. The point of a TCB is to have a well-defined computing base which can protect against specific threats. This requires you to be clear about exactly what functionality requires that it be trusted, where it sits in the system, and how the other components in the system rely on it: what trust relationships they have. I was speaking to a colleague just yesterday who was relaying a story of software project who said, “we’ve reduced our TCB to this tiny component by designing it very carefully and checking how we implement it”, but who overlooked the fact that the rest of the stack – which contained a complete Linux distribution and applications – could be no more trusted than before. The threat model (if there was one – we didn’t get into details) seemed to assume that only the TCB would be attacked, which missed the point entirely: it just added another “turtle” to the stack, without actually fixing the problem that was presumably at issue: that of improving the security of the system.

Reducing the TCB by artificially defining what the TCB is to suit your capabilities or particular beliefs around what the TCB specifically should be protecting against is not only unhelpful but actively counter-productive. This is because it ignores the fact that a TCB is there to serve the needs of a broader system, and if it is considered in isolation, then it becomes irrelevant: what is it acting as a base for?

In conclusion, it’s all very well saying “we have a tiny TCB”, but you need to know what you’re protecting, from what, and how.

Intentional laziness

Identifying a time and then protecting that time is vital.

Over the past year[1], since Covid-19 struck us, one of the things that has been a notable is … well, the lack of notable things. Specifically, we’ve been deprived of many of the occasions that we’d use to mark our year, or to break the day-to-day grind: family holidays, the ability to visit a favourite restaurant, festivals, concerts, sporting events, even popping round to enjoy drinks or a barbecue at a friend’s house. The things we’d look forward to as a way of breaking the monotony of working life – or even of just providing something a bit different to a job we actively enjoy – have been difficult to come by.

This has led to rather odd way of being. It’s easy either to get really, really stuck into work tasks (whether that’s employed work, school work, voluntary work or unpaid work such as childcare or household management), or to find yourself just doing nothing substantive for long stretches of time. You know: just scrolling down your favourite social media feed, playing random games on your phone – all the while feeling guilty that you’re not doing what you should be doing. I’ve certainly found myself doing the latter from time to time when I feel I should be working, and have overcompensated by forcing myself to work longer hours, or to check emails at 10pm when I should get thinking about heading to bed, for instance. So, like many of us, I think, I get stuck into one of two modes:

  1. messing around on mindless tasks, or
  2. working longer and harder than I should be.

The worse thing about the first of these is that I’m not really relaxing when I’m doing them, partly because much of my mind is on things which I feel I ought to be doing.

There are ways to try to fix this, one of which is to be careful about the hours you work or the tasks you perform, if you’re more task-oriented in the role you do, and then to set yourself non-work tasks to fill up the rest of the time. Mowing the lawn, doing the ironing, planting bulbs, doing the shopping, putting the washing out – the tasks that need to get done, but which you might to prefer to put off, or which you just can’t quite find time to do because you’re stuck in the messing/working cycle. This focus on tasks that actually need to be done, but which aren’t work (and divert you from the senseless non-tasks) has a lot to be said for it, and (particularly if you live with other people). It’s likely to provide social benefits as well (you’ll improve the quality of the environment you live in, or you’ll just get shouted at less), but it misses something: it’s not “down-time”.

By down-time, I mean time set aside specifically not to do things. It’s a concept associated with the word “Sabbath”, an Anglicisation of the Hebrew word “shabbat”, which can be translated as “rest” or “cessation”. I particularly like the second translation (though given my lack of understanding of Hebrew, I’m just going to have to accept the Internet’s word for the translation!), as the idea of ceasing what you’re doing, and making a conscious decision to do so, is something I think that it’s easy to miss. That’s true even in normal times, but with fewer markers in our lives for when to slow down and take time for ourselves – a feature of many of our lives in the world of Covid-19 – it’s all too simple just to forget, or to kid ourselves that those endless hours of brainless tapping or scrolling are actually some sort of rest for our minds and souls.

Whether you choose a whole day to rest/cease every week, set aside an hour after the kids have gone to bed, get up an hour early, give yourself half an hour over lunch to walk or cycle or do something else, it doesn’t matter. What I know I need to do (and I think it’s true of others, too), is to practice intentional laziness. This isn’t the same as doing things which you may find relaxing to some degree (I enjoy ironing, I know people who like cleaning the kitchen), but which need to be done: it’s about giving yourself permission not to do something. This can be really, really hard, particularly if you care for other people, have a long commute or a high pressure job, but it’s also really important for our longer-term well-being.

You also need to plan to be lazy. This seems counter-intuitive, at least to me, but if you haven’t set aside time and given yourself permission to relax and cease your other activities, you’ll feel guilty, and then you won’t be relaxing properly. Identifying a time to read a book, watch some low-quality boxsets, ring up a friend for a gossip on the phone or just have a “sneaky nap”, and then protecting that time is worthwhile. No – it’s more than worthwhile: it’s vital.

I’m aware, as I write this, that I’m in the very privileged position of being able to do this fairly easily[2], when for some people, it’s very difficult. Sometimes, we may need to defer these times and to plan a weekend away from the kids, a night out or an evening in front of the television for a week, or even a month or more from now. Planning it gives us something to hold on to, though: a break from the “everyday-ness” which can grind us down. But if we don’t have something to look forward to, a time that we protect, for ourselves, to be intentionally lazy, then our long-term physical, emotional and mental health will suffer.


1 – or two years, or maybe a decade. No-one seems to know.

2 – this doesn’t mean that I do, however.

Dependencies and supply chains

A dependency on a component is one which that an application or component needs to work

Supply chain security is really, really hot right now. It’s something which folks in the “real world” of manufactured things have worried about for years – you might be surprised (and worried) how much effort aircraft operators need to pay to “counterfeit parts”, and I wish I hadn’t just searched online the words “counterfeit pharmaceutical” – but the world of software had a rude wake-up call recently with the Solarwinds hack (or crack, if you prefer). This isn’t the place to go over that: you’ll be able to find many, many articles if you search on that. In fact, many companies have been worrying about this for a while, but the change is that it’s an issue which is now out in the open, giving more leverage to those who want more transparency around what software they consume in their products or services.

When we in computing (particularly software) think about supply chains, we generally talk about “dependencies”, and I thought it might be useful to write a short article explaining the main dependency types.

What is a dependency?

A dependency on a component is one which that an application or component needs to work, and they are generally considered to come in two types:

  • build-time dependencies
  • run-time dependencies.

Let’s talk about those two types in turn.

Build-time dependencies

these are components which are required in order to build (typically compile and package) your application or library. For example, if I’m writing a program in Rust, I have a dependency on the compiler if I want to create an application. I’m actually likely to have many more run-time dependencies, however. How those dependencies are made visible to me will depend on the programming language and the environment that I’m building in.

Some languages, for instance, may have filesystem support built in, but others will require you to “import” one or more libraries in order to read and write files. Importing a library basically tells your build-time environment to look somewhere (local disk, online repository, etc.) for a library, and then bring it into the application, allowing its capabilities to be used. In some cases, you will be taking pre-built libraries, and in others, your build environment may insist on building them itself. Languages like Rust have clever environments which can look for new versions of a library, download it and compile it without your having to worry about it yourself (though you can if you want!).

To get back to your file system example, even if the language does come with built-in filesystem support, you may decide to import a different library – maybe you need some fancy distributed, sharded file system, for instance – from a different supplier. Other capabilities may not be provided by the language, or may be higher-level capabilities: JSON serialisation or HTTPS support, for instance. Whether that library is available in open source may have a large impact on your decision as to whether or not to use it.

Build-time dependencies, then, require you to have the pieces you need – either pre-built or in source code form – at the time that you’re building your application or library.

Run-time dependencies

Run-time dependencies, as the name implies, only come into play when you actually want to run your application. We can think of there being two types of run-time dependency:

  1. service dependency – this may not be the official term, but think of an application which needs to write some data to a window on a monitor screen: in most cases, there’s already a display manager and a window manager running on the machine, so all the application needs to do is contact it, and communicate the right data over an API. Sometimes, the underlying operating system may need to start these managers first, but it’s not the application itself which is having to do that. These are local services, but remote services – accessing a database, for instance – operate in the same sort of way. As long as the application can contact and communicate with the database, it doesn’t need to do much itself. There’s still a dependency, and things can definitely go wrong, but it’s a weak coupling to an external application or service.
  2. dynamic linking – this is where an application needs access to a library at run-time, but rather than having added it at build-time (“static linking”), it relies on the underlying operating system to provide a link to the library when it starts executing. This means that the application doesn’t need to be as large (it’s not “carrying” the functionality with it when it’s installed), but it does require that the version that the operating system provides is compatible with what’s expected, and does the right thing.

Conclusion

I’ve resisted the temptation to go into the impacts of these different types of dependency in terms of their impact on security. That’s a much longer article – or set of articles – but it’s worth considering where in the supply chain we consider these dependencies to live, and who controls them. Do I expect application developers to check every single language dependency, or just imported libraries? To what extent should application developers design in protections from malicious (or just poorly-written) dynamically-linked libraries? Where does the responsibility lie for service dependencies – particularly remote ones?

These are all complex questions: the supply chain is not a simple topic (partly because there is not just one supply chain, but many of them), and organisations need to think hard about how they work.