<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.0">Jekyll</generator><link href="http://blog.ghostinashell.com/feed.xml" rel="self" type="application/atom+xml" /><link href="http://blog.ghostinashell.com/" rel="alternate" type="text/html" /><updated>2022-04-14T07:53:43+00:00</updated><id>http://blog.ghostinashell.com/feed.xml</id><title type="html">la ritual de exploración</title><subtitle></subtitle><entry><title type="html">Please don’t teach your customers to trust unknown numbers</title><link href="http://blog.ghostinashell.com/security/privacy/2022/04/14/how-not-to-contact-your-customers.html" rel="alternate" type="text/html" title="Please don’t teach your customers to trust unknown numbers" /><published>2022-04-14T02:00:00+00:00</published><updated>2022-04-14T02:00:00+00:00</updated><id>http://blog.ghostinashell.com/security/privacy/2022/04/14/how-not-to-contact-your-customers</id><content type="html" xml:base="http://blog.ghostinashell.com/security/privacy/2022/04/14/how-not-to-contact-your-customers.html">&lt;p&gt;Teaching customers to trust cold-calls from random mobile numbers is not something we should be doing these days….&lt;/p&gt;

&lt;p&gt;A few days ago I had a missed call from a mobile number I didn’t recognise. The caller did not leave a voicemail.&lt;/p&gt;

&lt;p&gt;So, I called it back. I usually would not, but looking at &lt;a href=&quot;https://www.reverseaustralia.com/&quot;&gt;reverseaustralia.com&lt;/a&gt; I could see that it &lt;em&gt;may&lt;/em&gt; be my health insurance provider. The number is not listed anywhere that I could find on their website.&lt;/p&gt;

&lt;p&gt;*“Hi, you’ve reached &lt;insurance company=&quot;&quot; name=&quot;&quot;&gt;…. could I please have your policy number”*&lt;/insurance&gt;&lt;/p&gt;

&lt;p&gt;At which point I asked how I can verify they’re who they say they are, and advised the general issue I had with this situation. They basically just insisted they are who they say they are… so I said I’ll call back on the listed number on the website.&lt;/p&gt;

&lt;p&gt;Which I did, and sure enough it was actually the company who had called me. I asked about this mobile number and said my piece about how this feels dodgy… and was advised this is actually a ‘security feature’ used by their ‘backend team’.&lt;/p&gt;

&lt;p&gt;They apparently use &lt;strong&gt;a system of cycling mobile numbers for outbound calls, and there’s apparently no process in place of how to help customers verify the caller, and nothing on the website about this practice.&lt;/strong&gt; There’s also little information for their callcenter on what to say to customers asking about it as he was grasping at straws somewhat trying to answer my questions - &lt;em&gt;“It is secure because they ask people security verification questions when they call them.”&lt;/em&gt; - which is the problem here!&lt;/p&gt;

&lt;p&gt;There has been a growing awareness of vishing, and many organisations are trying to educate people to this threat. If you’re recieving a call from an unverified caller, don’t trust it. &lt;em&gt;Teaching your customers to trust cold-calls from random numbers, asking for your policy details and your security verification answers is poor practice&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I feel like a much better approach would involve:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Calls come from a number listed on the website.&lt;/li&gt;
  &lt;li&gt;Leave a voicemail, advising to call a listed number for the company.&lt;/li&gt;
  &lt;li&gt;Write about the process on the website.&lt;/li&gt;
  &lt;li&gt;Give callcenter staff a playbook and info about how privacy is ensured during outbound calls.&lt;/li&gt;
  &lt;li&gt;I believe there’s a method for companies to have their numbers show up as text, I’m not much of a telco expert but surely it’s available if you’re a huge organisation such as this.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do you have a story like this? I’m keen to hear in the comments about your experiences and other ideas of how companies could be making outbound calls in a much safer manner.&lt;/p&gt;

&lt;p&gt;I’ve not embedded the company name in this post, I will likely disclose it in a week or after I have a response from the email I have sent them…. which isn’t a security email, just the general info email as that’s all they list on their site.&lt;/p&gt;</content><author><name></name></author><category term="security" /><category term="privacy" /><summary type="html">Teaching customers to trust cold-calls from random mobile numbers is not something we should be doing these days….</summary></entry><entry><title type="html">A Container Security Maturity Model</title><link href="http://blog.ghostinashell.com/security/docker/cloudnative/containers/2022/04/11/container-maturity-model.html" rel="alternate" type="text/html" title="A Container Security Maturity Model" /><published>2022-04-11T02:00:00+00:00</published><updated>2022-04-11T02:00:00+00:00</updated><id>http://blog.ghostinashell.com/security/docker/cloudnative/containers/2022/04/11/container-maturity-model</id><content type="html" xml:base="http://blog.ghostinashell.com/security/docker/cloudnative/containers/2022/04/11/container-maturity-model.html">&lt;p&gt;Putting the CNCF Cloud Native Security Whitepaper into practice. An updated version of this post I published last month, now with the model in public Google Sheets instead of the repo as well as various edits.&lt;/p&gt;

&lt;p&gt;This post is about building &amp;amp; using a maturity model to help assess &amp;amp; prioritise a subject area within cybersecurity. Specifically it is focused on drawing from the &lt;a href=&quot;https://github.com/cncf/tag-security/blob/main/security-whitepaper/CNCF_cloud-native-security-whitepaper-Nov2020.pdf&quot;&gt;CNCF Cloud Native Security Whitepaper&lt;/a&gt; to measure the security posture of container workloads, from development through runtime. The process of making such a model should generally be useful outside of just container security.&lt;/p&gt;

&lt;p&gt;Perhaps you’re a security engineer or an engineering lead. Cloud-first, shipping most things in containers. You may have more than a suspician that your container ecosystem lacks security features, that there are various risks and that there is a potential need to uplift. But it’s also a large subject area to address narrowly, there is a lot of complexity.&lt;/p&gt;

&lt;p&gt;How can you effectively build a business case and determine your priorities within a large, complex set of systems and practices? I like to draw from a public model or framework, others in the industry have given input based on their experience and situations they have faced, and often showing a precedent of ‘industry practice’ will be of great help.&lt;/p&gt;

&lt;p&gt;The resulting model is available in Google Sheets &lt;a href=&quot;https://docs.google.com/spreadsheets/d/1WXcBGgYKEi7xTR0CqJ1RBluWNNPJqNj3O90Gu8swALQ/edit?usp=sharing&quot;&gt;here&lt;/a&gt;. If anyone wants commenter access let me know.&lt;/p&gt;

&lt;h2 id=&quot;enter-capability-maturity-models&quot;&gt;Enter Capability Maturity Models&lt;/h2&gt;

&lt;p&gt;A &lt;a href=&quot;https://en.wikipedia.org/wiki/Capability_Maturity_Model&quot;&gt;Capability Maturity Model (CMM)&lt;/a&gt;, or variation of such, is often employed when assessing software development processes. The general apprach is to have key process areas, each of which contain a set of related activities, and each activity has a set of criterea which are marked with a rating of 1-5, with 3 often being ‘good’ or ‘defined’. An example used within cybersecurity is &lt;a href=&quot;https://www.bsimm.com/&quot;&gt;Building Security in Maturity Model (BSIMM)&lt;/a&gt; - “an objective, data-driven evaluation that leaders seeking to improve their security postures can use to base decisions about resources, time, budget, and priorities”. It has a large community, but also complexity and a focus different to what we’re working on here. I want something ‘light touch’ and focused on the container ecosystem.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2022-02-09-container-maturity/cmm_levels.png&quot; alt=&quot;CMM Levels&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Capability Maturity Levels (from Wikipedea)&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;the-cloud-native-security-whitepaper&quot;&gt;The Cloud Native Security Whitepaper&lt;/h2&gt;

&lt;p&gt;In late 2020 the &lt;a href=&quot;https://github.com/cncf/tag-security&quot;&gt;Cloud Native Foundation TAG-Security&lt;/a&gt; published the &lt;a href=&quot;https://github.com/cncf/tag-security/blob/main/security-whitepaper/CNCF_cloud-native-security-whitepaper-Nov2020.pdf&quot;&gt;Cloud Native Security Whitepaper&lt;/a&gt;. This defines &amp;amp; describes lifecycle Stages within a Cloud Native ecosystem - &lt;strong&gt;Develop&lt;/strong&gt;, &lt;strong&gt;Distribute&lt;/strong&gt;, &lt;strong&gt;Deploy&lt;/strong&gt;, and &lt;strong&gt;Runtime&lt;/strong&gt; as depicted below.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2022-02-09-container-maturity/cncf_lifecycle.png&quot; alt=&quot;CNCF Lifecycle Stages&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Coud Native Lifecycle&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;These lifecycle phases can be used as process areas in a model, grouping the processes &amp;amp; activities relating to container security.&lt;/p&gt;

&lt;p&gt;There are other frameworks for looking at cloud &amp;amp; container ecosystems, such as the &lt;a href=&quot;https://kubernetes.io/docs/concepts/security/overview/&quot;&gt;4Cs&lt;/a&gt;, &lt;a href=&quot;https://www.redhat.com/architect/enterprise-architects-devsecops&quot;&gt;Redhat’s DevSecOps maturity model&lt;/a&gt;, and vendor models such as those seen on Aqua security homepage. As the &lt;a href=&quot;https://www.cncf.io/&quot;&gt;CNCF&lt;/a&gt; is well placed as a vendor-neutral Cloud Native industry body, and their Security-TAG is extremely active and knowledgeable I felt that basing a model on the Cloud Native Security Whitepaper was most suitable.&lt;/p&gt;

&lt;h2 id=&quot;building-the-model&quot;&gt;Building the Model&lt;/h2&gt;

&lt;p&gt;Containers are not everything within cloud native, they’re somewhat intrinsic but there are various aspects of the lifecycle which may not be entirely relevant. Assessing an organisations entire cloud native approach is a much broader scope than I wanted or needed, as such various items have been omitted, or have been included but will get little direct attention from a container security program as they are already covered by other areas - an AppSec program (SCA, Secrets in Code, SAST), Cloud Security (eg AWS security policy adherance), SecOps (DFIR). The application sourcecode that will be hosted and the AWS account configuration are not covered in my scope. There will always be overlap or gaps, so I have tried to address these where appropriate.&lt;/p&gt;

&lt;p&gt;The CNCF are also developing a &lt;a href=&quot;https://cnsmap.github.io/&quot;&gt;Cloud Native Security Map&lt;/a&gt; which aims to map available tools, benchmarks and practices to the lifecycles.&lt;/p&gt;

&lt;p&gt;The sections and rows in my model are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Develop
    &lt;ul&gt;
      &lt;li&gt;Standards&lt;/li&gt;
      &lt;li&gt;Image Manifests&lt;/li&gt;
      &lt;li&gt;Infrastructure as Code Manifests&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Distribute
    &lt;ul&gt;
      &lt;li&gt;Image Builds&lt;/li&gt;
      &lt;li&gt;Image Registry Trust&lt;/li&gt;
      &lt;li&gt;Image Registry Store&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Deploy
    &lt;ul&gt;
      &lt;li&gt;Image Trust&lt;/li&gt;
      &lt;li&gt;Pre-flight Configuration Controls&lt;/li&gt;
      &lt;li&gt;Pre-flight Policy Controls&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Runtime
    &lt;ul&gt;
      &lt;li&gt;Policy Enforcement&lt;/li&gt;
      &lt;li&gt;Identity &amp;amp; Access Management&lt;/li&gt;
      &lt;li&gt;Secure Storage&lt;/li&gt;
      &lt;li&gt;Secrets Management&lt;/li&gt;
      &lt;li&gt;Secure Network&lt;/li&gt;
      &lt;li&gt;Observability &amp;amp; Incident Response&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For ease of getting started, Excel was chosen, with a star chart displaying where we want to be (green) and where we are (red) based on a self-rating.&lt;/p&gt;

&lt;p&gt;I spent a chunk of time thinking about each area and got it into something that I felt was workable. The definitions for each row are generally based upon the CNCF Security Whitepaper, and also largely informed by my individual experience of the capabilities, standards, ‘good practices’ in existence as well as what I’ve experienced over the years working in infosec. It’s imperfect and hopefully can grow and adjust over time.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2022-02-09-container-maturity/star.png&quot; alt=&quot;Capability Star&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Visualising Maturity&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;utilising-the-model&quot;&gt;Utilising the Model&lt;/h2&gt;

&lt;p&gt;I rated each of the sections based on info I could find and what I knew, and got a nice star graph. Great! So, what to do with it…. put it on a billboard with “The end is near!” scrawled under it? No, let’s get a practical outcome. The measurement is there to help us drive a program of work, so let’s do that.&lt;/p&gt;

&lt;p&gt;Based on the Whitepaper, the rows of the model and the technical and policy capabilities in the organistation I populated a Miro board to use in a group session. Each lifecycle phase is broken into sections, and in each we have our existing practices, and an area to note our gaps. There is also a box in each section for ‘research tasks’, items that may be noted but we’re not sure how useful it could be, which tech to go with etc.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2022-02-09-container-maturity/miro-zoomed-out.png&quot; alt=&quot;Miro High Level&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Utilising Miro For Group Gap Analysis&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2022-02-09-container-maturity/miro-develop.png&quot; alt=&quot;Miro Develop Lifecycle&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Close Up of the Develop Lifecycle Stage within Miro&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A session was held with our relevant security folks and most importantly with those who engineer container-based environments at an organisational practice level. This session was around 90 minutes where the model &amp;amp; lifecycle was introduced and then we went through the various stages giving people time to add notes. Before moving to the next section we’d quickly summarise and clarify, at the end of the session I got some overall feelings from people and gathered various themes, clarifying some of the items.&lt;/p&gt;

&lt;p&gt;From this I went away and worked on a plan. We utilise Jira and so I took the lifecycle stages and themes identified within these as Epics, within each listing out the various gaps as Tasks or Stories - worded in such a way to highlight the remedial work and linked all together using a label plus another label for the lifecycle stage, eg ‘cncf-develop’. The various Epics were grouped under Initiatives. An example would be an Initative of “Implement &amp;amp; Enforce Security Capabilities In Image Builds”, under which one of the Epics of “Aggregate Image &amp;amp; Container Metadata into SIEM”, and within this one of the tasks of “Correlate Running Container IDs With Image Vulnerability Data”. Jira can be a bit clunky in organising complex pieces of work - these systems all are a bit - but it was helpful to get a view of the actual work. For more on structuring work within Jira there is a decent article from Atlassian &lt;a href=&quot;https://www.atlassian.com/agile/project-management/epics-stories-themes&quot;&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once it’s all in Jira it’s still just a big bunch of tasks. This is where the model helps to priopritise. We’d marked where we want to be, we’d marked where we are, and we have Jira labels allowing us to narrow into the areas. For me with starting such work I look at where we have the biggest gap, then which is the simplest to do. From here we know what is first up, and can reasonably plan for the next few months. Anything after that can be planned later. I won’t go into detail of what we picked - for you it might be implementing a break-build capability pre-push based on an agreed vulnerability threshold. It could be implementing an admission controller to allow policy adherence within your kubernetes stack. It all depends on your own outcome from the model.&lt;/p&gt;

&lt;h2 id=&quot;reflections&quot;&gt;Reflections&lt;/h2&gt;

&lt;p&gt;I like simple visual reprentations, based on some reasonable process to get there, and I’m happy with the result. It’s a bit rough, some of the language could be adjusted and more measurable metric definitions worked toward.&lt;/p&gt;

&lt;p&gt;Having a published whitepaper from an industry body (the wonderful &lt;a href=&quot;https://www.cncf.io/&quot;&gt;CNCF&lt;/a&gt; in this case) is incredibly valuable.&lt;/p&gt;

&lt;p&gt;Having a published whitepaper from an industry body is incredibly valuable. Having the resultant visualisation of current and hoped maturity has been very effective in describing our problems and deciding where to increase resources.&lt;/p&gt;

&lt;p&gt;Creating a model helped get my head around this complex space. Cloud Native and within that container security is entwined with all aspects of application &amp;amp; platform development and operations. Scoping helped to give a clearer picture of the container domain, and what was relevant within my organisation.I found that the Cloud Native Lifecycle Phases ends up with the largest proportion of items in Distribute &amp;amp; Runtime. This makes sense when you consider CI/CD often being the central place of earliest value stage gating (Distribute), and all of the moving pieces that could be involved in your production environments (Runtime). Once again, scoping can help here - especially with runtime - e.g EDR might be a pre-existing process handled by your SecOps team and wider than just cloud or containers, in a similar way you may already have standard Base OS hardening processes - so the container base host is out of scope.&lt;/p&gt;

&lt;p&gt;It is hard to box all items into the phases - areas cross over, such as build capabilities (Distribute) being largely the same as IDE/local tooling in many situations (Develop). This is always the case with complex systems, trying to link these together in the task capture tool such as Jira or make a decision for the sake of progressing the work helps somewhat. The aim isn’t to neatly categorise things at the end of the day but to strengthen your security posture.&lt;/p&gt;

&lt;p&gt;I used Miro for collaboration. People generally need to use it regularly to feel comfortable contributing. It is a great tool, the ability to visualise and all work together is especially important in remote work, but if your organisation suffers from a lack of standardisation in collaboration tool there will often be a barrier to effective contributions based on the comfort levels with the tool.&lt;/p&gt;

&lt;p&gt;Jira is also hard - grouping things, prioritisation, visualising are all difficult at the best of times let alone if your workspace isn’t set up all that well. Once I had the uplift items in here though it was very easy to link to, show how long we’ve had these issues logged, drag items into a roadmap and collect relevant information.&lt;/p&gt;

&lt;p&gt;The whitepaper &amp;amp; lifecycle are evolving, the &lt;a href=&quot;https://github.com/cncf/tag-security&quot;&gt;CNCF Tag-Security&lt;/a&gt; is maintaining this great work. A new version of the whitepaper is in RFC now &amp;amp; the previously mentioned &lt;a href=&quot;https://cnsmap.github.io/&quot;&gt;CNCF Security Map&lt;/a&gt; continues to collect open source tooling options. A space I’ll watch closely and hopefully get more involved in.&lt;/p&gt;</content><author><name></name></author><category term="security" /><category term="docker" /><category term="cloudnative" /><category term="containers" /><summary type="html">Putting the CNCF Cloud Native Security Whitepaper into practice. An updated version of this post I published last month, now with the model in public Google Sheets instead of the repo as well as various edits.</summary></entry><entry><title type="html">Image Vulnerability Scanners Compared, Pt1</title><link href="http://blog.ghostinashell.com/programming/linux/security/docker/2021/10/31/imagescanners1.html" rel="alternate" type="text/html" title="Image Vulnerability Scanners Compared, Pt1" /><published>2021-10-31T02:00:00+00:00</published><updated>2021-10-31T02:00:00+00:00</updated><id>http://blog.ghostinashell.com/programming/linux/security/docker/2021/10/31/imagescanners1</id><content type="html" xml:base="http://blog.ghostinashell.com/programming/linux/security/docker/2021/10/31/imagescanners1.html">&lt;p&gt;I’m looking at the capabilities and results from three container image vulnerability scanners - Trivy, Snyk &amp;amp; AWS ECR Scanning.&lt;/p&gt;

&lt;p&gt;In this first segment I look at set up of the scans and gather vulnerability results for both a patched and unpatched image. 
In part 2 I will have a look at which appears to be more accurate in it’s findings, and other available features such as misconfiguration detection.&lt;/p&gt;

&lt;h2 id=&quot;introducing-the-tools&quot;&gt;Introducing the tools&lt;/h2&gt;

&lt;h3 id=&quot;trivy&quot;&gt;Trivy&lt;/h3&gt;

&lt;p&gt;Trivy is an open source vulnerability &amp;amp; misconfiguration scanner maintained by Aqua Security, 
and is very quick and easy to get started.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/aquasecurity/trivy&quot;&gt;Homepage&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://aquasecurity.github.io/trivy/v0.20.2/getting-started/overview/&quot;&gt;Installation steps&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;❯ trivy --version
Version: 0.20.2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Run with:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;trivy &amp;lt;image&amp;gt; # for a table to stdout
trivy -q -f json &amp;lt;image&amp;gt; # for json output
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A finding (in json) looks like this:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  {
    &quot;VulnerabilityID&quot;: &quot;CVE-2021-22945&quot;,
    &quot;PkgName&quot;: &quot;curl&quot;,
    &quot;InstalledVersion&quot;: &quot;7.78.0-r0&quot;,
    &quot;FixedVersion&quot;: &quot;7.79.0-r0&quot;,
    &quot;Layer&quot;: {
      &quot;DiffID&quot;: &quot;sha256:a1920ef522ec8f49831ef40db2c3ad4777da04239270e6698d1674ebb90c8c82&quot;
    },
    &quot;SeveritySource&quot;: &quot;nvd&quot;,
    &quot;PrimaryURL&quot;: &quot;https://avd.aquasec.com/nvd/cve-2021-22945&quot;,
    &quot;Title&quot;: &quot;curl: use-after-free and double-free in MQTT sending&quot;,
    &quot;Description&quot;: &quot;When sending data to an MQTT server, libcurl &amp;lt;= 7.73.0 and 7.78.0 could in some circumstances erroneously keep a pointer to an already freed memory area and bo
th use that again in a subsequent call to send data and also free it *again*.&quot;,
    &quot;Severity&quot;: &quot;CRITICAL&quot;,
    &quot;CweIDs&quot;: [
      &quot;CWE-415&quot;
    ],
    &quot;CVSS&quot;: {
      &quot;nvd&quot;: {
        &quot;V2Vector&quot;: &quot;AV:N/AC:M/Au:N/C:P/I:N/A:P&quot;,
        &quot;V3Vector&quot;: &quot;CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:H&quot;,
        &quot;V2Score&quot;: 5.8,
        &quot;V3Score&quot;: 9.1
      },
      &quot;redhat&quot;: {
        &quot;V3Vector&quot;: &quot;CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:H&quot;,
        &quot;V3Score&quot;: 7.4
      }
    },
    &quot;References&quot;: [
      &quot;https://curl.se/docs/CVE-2021-22945.html&quot;,
      &quot;https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-22945&quot;,
      &quot;https://hackerone.com/reports/1269242&quot;,
      &quot;https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/RWLEC6YVEM2HWUBX67SDGPSY4CQB72OE/&quot;,
      &quot;https://security.netapp.com/advisory/ntap-20211029-0003/&quot;,
      &quot;https://ubuntu.com/security/notices/USN-5079-1&quot;,
      &quot;https://www.oracle.com/security-alerts/cpuoct2021.html&quot;
    ],
    &quot;PublishedDate&quot;: &quot;2021-09-23T13:15:00Z&quot;,
    &quot;LastModifiedDate&quot;: &quot;2021-10-29T13:15:00Z&quot;
  },
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As well as vulnerability findings Trivy (in it’s json output) provides a lot of information about the image,
including the build steps and layer history, image env, cmd, entry-pont, distro version etc. There’s quite 
a lot so I’m not pasting it here, but I do recommend having a look at this.&lt;/p&gt;

&lt;p&gt;I will use the following jq filter to show succinct vulnerability information:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jq '.Results[].Vulnerabilities[] | {&quot;ID&quot;: .VulnerabilityID, &quot;name&quot;: .Title, &quot;severity&quot;: .Severity, &quot;pkgname&quot;: .PkgName, &quot;installedversion&quot;: .InstalledVersion, &quot;fixedversion&quot;: .FixedVersion}'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Pricing&lt;/strong&gt;: Open Source / Free&lt;/p&gt;

&lt;h3 id=&quot;snyk&quot;&gt;Snyk&lt;/h3&gt;

&lt;p&gt;Snyk is a vulnerability scanner and SaaS. They provide a range of capabilities such as open source dependency scans,
IaC and container scanning.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://snyk.io/&quot;&gt;Homepage&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.snyk.io/features/snyk-cli/install-the-snyk-cli&quot;&gt;Installation steps&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;❯ snyk --version
1.745.0 (standalone)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Run with:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker scan &amp;lt;image&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There is a json output, but I like the grepable output and bundling of vulnerabilities presented by default on the CLI
for what I’m doing here.  More information is available in json by passing in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--json&lt;/code&gt; if desired.&lt;/p&gt;

&lt;p&gt;A finding  looks like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;✗ Critical severity vulnerability found in curl/libcurl
  Description: Double Free
  Info: https://snyk.io/vuln/SNYK-ALPINE313-CURL-1585246
  Introduced through: curl/libcurl@7.78.0-r0, curl/curl@7.78.0-r0
  From: curl/libcurl@7.78.0-r0
  From: curl/curl@7.78.0-r0 &amp;gt; curl/libcurl@7.78.0-r0
  From: curl/curl@7.78.0-r0
  Fixed in: 7.79.0-r0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Pricing&lt;/strong&gt;: Free for individuals and small teams, this has some limitations in features available which don’t affect this CLI type of testing.&lt;/p&gt;

&lt;h3 id=&quot;aws-ecr&quot;&gt;AWS ECR&lt;/h3&gt;

&lt;p&gt;AWS has an image scanning capability, which can be used to scan images within an AWS ECR repository. According to their docs “Each container image may be scanned once per 24 hours. Amazon ECR uses the Common Vulnerabilities and Exposures (CVEs) database from the open-source Clair project”&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-scanning.html&quot;&gt;Homepage&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Log into an ECR registry with the docker client. See the &lt;a href=&quot;https://docs.aws.amazon.com/AmazonECR/latest/userguide/docker-push-ecr-image.html&quot;&gt;AWS Docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create a repository if you haven’t already. See the &lt;a href=&quot;https://docs.aws.amazon.com/AmazonECR/latest/userguide/repository-create.html&quot;&gt;AWS Docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ECR scans from the registry, so you need to push to the repository, set off a scan and then retrieve the results:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker tag nginxlab:latest account.dkr.ecr.region.amazonaws.com/nginxlab:latest
docker push account.dkr.ecr.region.amazonaws.com/nginxlab:latest
aws ecr start-image-scan --repository-name nginxlab --image-id imageTag=latest
aws ecr describe-image-scan-findings --repository-name nginxlab --image-id imageTag=latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A finding looks like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{
  &quot;name&quot;: &quot;CVE-2021-22947&quot;,
  &quot;uri&quot;: &quot;https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-22947&quot;,
  &quot;severity&quot;: &quot;MEDIUM&quot;,
  &quot;attributes&quot;: [
    {
      &quot;key&quot;: &quot;package_version&quot;,
      &quot;value&quot;: &quot;7.78.0-r0&quot;
    },
    {
      &quot;key&quot;: &quot;package_name&quot;,
      &quot;value&quot;: &quot;curl&quot;
    },
    {
      &quot;key&quot;: &quot;CVSS2_VECTOR&quot;,
      &quot;value&quot;: &quot;AV:N/AC:M/Au:N/C:N/I:P/A:N&quot;
    },
    {
      &quot;key&quot;: &quot;CVSS2_SCORE&quot;,
      &quot;value&quot;: &quot;4.3&quot;
    }
  ]
},
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…feels a bit sparse to me.&lt;/p&gt;

&lt;p&gt;Summary information is also presented:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &quot;imageScanCompletedAt&quot;: &quot;2021-11-01T11:58:01+11:00&quot;,
    &quot;vulnerabilitySourceUpdatedAt&quot;: &quot;2021-11-01T03:11:25+11:00&quot;,
    &quot;findingSeverityCounts&quot;: {
      &quot;MEDIUM&quot;: 3,
      &quot;LOW&quot;: 2
    }
  },
  &quot;registryId&quot;: &quot;1234567890&quot;,
  &quot;repositoryName&quot;: &quot;nginxlab&quot;,
  &quot;imageId&quot;: {
    &quot;imageDigest&quot;: &quot;sha256:b6e9f2d1354314363eb6c5afce9a186214afe2c5f1767dbc3397b1c87bcb3745&quot;,
    &quot;imageTag&quot;: &quot;latest&quot;
  },
  &quot;imageScanStatus&quot;: {
    &quot;status&quot;: &quot;COMPLETE&quot;,
    &quot;description&quot;: &quot;The scan was completed successfully.&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Pricing&lt;/strong&gt;: From what I can tell ECR vulnerability scanning doesn’t incur a charge, but I can’t find any docs on this.
The &lt;a href=&quot;https://aws.amazon.com/ecr/pricing/&quot;&gt;ECR Pricing doc&lt;/a&gt; suggests fees are only for the amount of data stored or transferred. Probably for a small self-hosted
project this might be a few dollars per month. If you’re an organisation running builds thousands of times per day and have
to upload each image to ECR before a vuln scan step then it could start to add up.&lt;/p&gt;

&lt;p&gt;I will be using the following jq filter to present a succinct view of the findings from ECR:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jq '.imageScanFindings.findings[] | {&quot;id&quot;: .name,&quot;severity&quot;: .severity,&quot;pkgname&quot;: .attributes[1].value,&quot;installedversion&quot;:.attributes[0].value}'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;first-image---nginx-alpine&quot;&gt;First Image - Nginx Alpine&lt;/h1&gt;

&lt;p&gt;Running a basic health check endpoint and no configurations altered.&lt;/p&gt;

&lt;h2 id=&quot;unpatched&quot;&gt;Unpatched&lt;/h2&gt;

&lt;p&gt;No OS upgrades applied via APK.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;FROM nginx:1.20-alpine
RUN echo 'server {location /health {default_type text/plain; return 200 &quot;OK&quot;;}}' \
    &amp;gt; /etc/nginx/conf.d/default.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Built with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker build . -t nginxlab:latest&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;trivy-1&quot;&gt;Trivy&lt;/h3&gt;

&lt;p&gt;2 Critical, 2 High, 3 Medium&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{
  &quot;id&quot;: &quot;CVE-2021-22945&quot;,
  &quot;name&quot;: &quot;curl: use-after-free and double-free in MQTT sending&quot;,
  &quot;severity&quot;: &quot;CRITICAL&quot;,
  &quot;pkgname&quot;: &quot;curl&quot;,
  &quot;installedversion&quot;: &quot;7.78.0-r0&quot;,
  &quot;fixedversion&quot;: &quot;7.79.0-r0&quot;
}
{
  &quot;id&quot;: &quot;CVE-2021-22946&quot;,
  &quot;name&quot;: &quot;curl: Requirement to use TLS not properly enforced for IMAP, POP3, and FTP protocols&quot;,
  &quot;severity&quot;: &quot;HIGH&quot;,
  &quot;pkgname&quot;: &quot;curl&quot;,
  &quot;installedversion&quot;: &quot;7.78.0-r0&quot;,
  &quot;fixedversion&quot;: &quot;7.79.0-r0&quot;
}
{
  &quot;id&quot;: &quot;CVE-2021-22947&quot;,
  &quot;name&quot;: &quot;curl: Server responses received before STARTTLS processed after TLS handshake&quot;,
  &quot;severity&quot;: &quot;MEDIUM&quot;,
  &quot;pkgname&quot;: &quot;curl&quot;,
  &quot;installedversion&quot;: &quot;7.78.0-r0&quot;,
  &quot;fixedversion&quot;: &quot;7.79.0-r0&quot;
}
{
  &quot;id&quot;: &quot;CVE-2021-22945&quot;,
  &quot;name&quot;: &quot;curl: use-after-free and double-free in MQTT sending&quot;,
  &quot;severity&quot;: &quot;CRITICAL&quot;,
  &quot;pkgname&quot;: &quot;libcurl&quot;,
  &quot;installedversion&quot;: &quot;7.78.0-r0&quot;,
  &quot;fixedversion&quot;: &quot;7.79.0-r0&quot;
}
{
  &quot;id&quot;: &quot;CVE-2021-22946&quot;,
  &quot;name&quot;: &quot;curl: Requirement to use TLS not properly enforced for IMAP, POP3, and FTP protocols&quot;,
  &quot;severity&quot;: &quot;HIGH&quot;,
  &quot;pkgname&quot;: &quot;libcurl&quot;,
  &quot;installedversion&quot;: &quot;7.78.0-r0&quot;,
  &quot;fixedversion&quot;: &quot;7.79.0-r0&quot;
}
{
  &quot;id&quot;: &quot;CVE-2021-22947&quot;,
  &quot;name&quot;: &quot;curl: Server responses received before STARTTLS processed after TLS handshake&quot;,
  &quot;severity&quot;: &quot;MEDIUM&quot;,
  &quot;pkgname&quot;: &quot;libcurl&quot;,
  &quot;installedversion&quot;: &quot;7.78.0-r0&quot;,
  &quot;fixedversion&quot;: &quot;7.79.0-r0&quot;
}
{
  &quot;id&quot;: &quot;CVE-2021-40528&quot;,
  &quot;name&quot;: &quot;libgcrypt: ElGamal implementation allows plaintext recovery&quot;,
  &quot;severity&quot;: &quot;MEDIUM&quot;,
  &quot;pkgname&quot;: &quot;libgcrypt&quot;,
  &quot;installedversion&quot;: &quot;1.8.8-r0&quot;,
  &quot;fixedversion&quot;: &quot;1.8.8-r1&quot;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;snyk-1&quot;&gt;Snyk&lt;/h3&gt;

&lt;p&gt;1 Critical, 1 High, 2 Medium&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;✗ Medium severity vulnerability found in libgcrypt/libgcrypt
  Description: Use of a Broken or Risky Cryptographic Algorithm
  Info: https://snyk.io/vuln/SNYK-ALPINE313-LIBGCRYPT-1585259
  Introduced through: libgcrypt/libgcrypt@1.8.8-r0, libxslt/libxslt@1.1.34-r0
  From: libgcrypt/libgcrypt@1.8.8-r0
  From: libxslt/libxslt@1.1.34-r0 &amp;gt; libgcrypt/libgcrypt@1.8.8-r0
  Fixed in: 1.8.8-r1

✗ Medium severity vulnerability found in curl/libcurl
  Description: Insufficient Verification of Data Authenticity
  Info: https://snyk.io/vuln/SNYK-ALPINE313-CURL-1585257
  Introduced through: curl/libcurl@7.78.0-r0, curl/curl@7.78.0-r0
  From: curl/libcurl@7.78.0-r0
  From: curl/curl@7.78.0-r0 &amp;gt; curl/libcurl@7.78.0-r0
  From: curl/curl@7.78.0-r0
  Fixed in: 7.79.0-r0

✗ High severity vulnerability found in curl/libcurl
  Description: Cleartext Transmission of Sensitive Information
  Info: https://snyk.io/vuln/SNYK-ALPINE313-CURL-1585248
  Introduced through: curl/libcurl@7.78.0-r0, curl/curl@7.78.0-r0
  From: curl/libcurl@7.78.0-r0
  From: curl/curl@7.78.0-r0 &amp;gt; curl/libcurl@7.78.0-r0
  From: curl/curl@7.78.0-r0
  Fixed in: 7.79.0-r0

✗ Critical severity vulnerability found in curl/libcurl
  Description: Double Free
  Info: https://snyk.io/vuln/SNYK-ALPINE313-CURL-1585246
  Introduced through: curl/libcurl@7.78.0-r0, curl/curl@7.78.0-r0
  From: curl/libcurl@7.78.0-r0
  From: curl/curl@7.78.0-r0 &amp;gt; curl/libcurl@7.78.0-r0
  From: curl/curl@7.78.0-r0
  Fixed in: 7.79.0-r0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;aws-ecr-1&quot;&gt;AWS ECR&lt;/h3&gt;

&lt;p&gt;3 Medium, 2 low&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{
  &quot;id&quot;: &quot;CVE-2021-22947&quot;,
  &quot;severity&quot;: &quot;MEDIUM&quot;,
  &quot;pkgname&quot;: &quot;curl&quot;,
  &quot;installedversion&quot;: &quot;7.78.0-r0&quot;
}
{
  &quot;id&quot;: &quot;CVE-2021-22945&quot;,
  &quot;severity&quot;: &quot;MEDIUM&quot;,
  &quot;pkgname&quot;: &quot;curl&quot;,
  &quot;installedversion&quot;: &quot;7.78.0-r0&quot;
}
{
  &quot;id&quot;: &quot;CVE-2021-22946&quot;,
  &quot;severity&quot;: &quot;MEDIUM&quot;,
  &quot;pkgname&quot;: &quot;curl&quot;,
  &quot;installedversion&quot;: &quot;7.78.0-r0&quot;
}
{
  &quot;id&quot;: &quot;CVE-2021-40528&quot;,
  &quot;severity&quot;: &quot;LOW&quot;,
  &quot;pkgname&quot;: &quot;libgcrypt&quot;,
  &quot;installedversion&quot;: &quot;1.8.8-r0&quot;
}
{
  &quot;id&quot;: &quot;CVE-2020-28928&quot;,
  &quot;severity&quot;: &quot;LOW&quot;,
  &quot;pkgname&quot;: &quot;musl&quot;,
  &quot;installedversion&quot;: &quot;1.2.2-r1&quot;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;patched&quot;&gt;Patched&lt;/h2&gt;

&lt;p&gt;This time upgrading via the distributions package manager.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;FROM nginx:1.20-alpine
RUN apk update &amp;amp;&amp;amp; apk upgrade
RUN echo 'server {location /health {default_type text/plain; return 200 &quot;OK&quot;;}}' \
    &amp;gt; /etc/nginx/conf.d/default.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;trivy-2&quot;&gt;Trivy&lt;/h3&gt;

&lt;p&gt;No vulnerabilities detected.&lt;/p&gt;

&lt;h3 id=&quot;snyk-2&quot;&gt;Snyk&lt;/h3&gt;

&lt;p&gt;No vulnerabilities detected.&lt;/p&gt;

&lt;h3 id=&quot;aws-ecr-2&quot;&gt;AWS ECR&lt;/h3&gt;

&lt;p&gt;AWS detected one Low severity vulnerability.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{
  &quot;id&quot;: &quot;CVE-2020-28928&quot;,
  &quot;severity&quot;: &quot;LOW&quot;,
  &quot;pkgname&quot;: &quot;musl&quot;,
  &quot;installedversion&quot;: &quot;1.2.2-r1&quot;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;… but was it accurate?&lt;/p&gt;

&lt;p&gt;The package version matches that which is reported:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;❯ docker run -it --rm nginxlab:latest apk list musl
musl-1.2.2-r1 x86_64 {musl} (MIT) [installed]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But looking at the &lt;a href=&quot;https://nvd.nist.gov/vuln/detail/CVE-2020-28928&quot;&gt;NVD record for CVE-2020-28928&lt;/a&gt; this version appears to not be affected:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In musl libc through 1.2.1, wcsnrtombs mishandles particular combinations of destination buffer size and source character limit&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So we have a false positive here due to an inaccurate match between the affected versions and that installed.&lt;/p&gt;

&lt;h2 id=&quot;part-2&quot;&gt;Part 2&lt;/h2&gt;

&lt;p&gt;Part 2 coming soon, with a deeper look at the results of from the unpatched image and a test of further scan features such as detection of misconfigurations.&lt;/p&gt;</content><author><name></name></author><category term="programming" /><category term="linux" /><category term="security" /><category term="docker" /><summary type="html">I’m looking at the capabilities and results from three container image vulnerability scanners - Trivy, Snyk &amp;amp; AWS ECR Scanning.</summary></entry><entry><title type="html">Yamaha MT4X Multitrack Cassette Recorder: Disassembly &amp;amp; Service</title><link href="http://blog.ghostinashell.com/electronics/cassette/4track/audio/2020/11/29/mt4x.html" rel="alternate" type="text/html" title="Yamaha MT4X Multitrack Cassette Recorder: Disassembly &amp;amp; Service" /><published>2020-11-29T02:00:00+00:00</published><updated>2020-11-29T02:00:00+00:00</updated><id>http://blog.ghostinashell.com/electronics/cassette/4track/audio/2020/11/29/mt4x</id><content type="html" xml:base="http://blog.ghostinashell.com/electronics/cassette/4track/audio/2020/11/29/mt4x.html">&lt;p&gt;I’ve recently serviced a couple of Yamaha mt4x four track cassette recorders.
Here I overview the process that I took and try to share info that I couldn’t easily find online myself.&lt;/p&gt;

&lt;p&gt;The images used are mostly from the restoration of a 100V machine I picked up on eBay. When I got it
 it wouldn’t power on and was very dirty inside and out. I have added images from another (240v) machine in some places
 to show differences or where I missed photographing something originally.&lt;/p&gt;

&lt;p&gt;There are probably some approaches that could be improved or things to know, so if you have any experience with these I’d be keen to hear your experience.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_1_dead.jpg&quot; alt=&quot;Dead &amp;amp; Dirty Yamaha MT4X&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Starting Point: Dead &amp;amp; Dirty MT4X&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;gather-tools--hardware&quot;&gt;Gather Tools &amp;amp; Hardware&lt;/h2&gt;

&lt;p&gt;Before unscrewing anything, you’ll want to make sure you’ve got a few things ready. I make sure I have the following available.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;2x Phillips Screwdrivers. A little one, and a bigger one.&lt;/li&gt;
  &lt;li&gt;Tweezers. I prefer to have both a bent and straight set on hand, but one will do.&lt;/li&gt;
  &lt;li&gt;Needle Nose Pliers.&lt;/li&gt;
  &lt;li&gt;A marker or two.&lt;/li&gt;
  &lt;li&gt;Plastic pry Tool. I have a cheap phone openining tool, but a public transport card usually works too.&lt;/li&gt;
  &lt;li&gt;Cotton/Q Tips. Best to have quite a few on hand.&lt;/li&gt;
  &lt;li&gt;Vernier Calipers are an optional which can help with measuring belts if you don’t know exactly what you need or have.&lt;/li&gt;
  &lt;li&gt;A toothbrush and/or stiff brush for cleaning plastic parts.&lt;/li&gt;
  &lt;li&gt;Electronic cleaning &amp;amp; lubricating solutions. I use:&lt;/li&gt;
  &lt;li&gt;
    &lt;ul&gt;
      &lt;li&gt;a solvent spray for jacks.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;ul&gt;
      &lt;li&gt;‘clean &amp;amp; lubricant’ with a spray nozzle adapter for pots &amp;amp; switches.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;ul&gt;
      &lt;li&gt;oil for motors &amp;amp; mechanical parts. Often I’ll use a sewing machine or motor oil but here am trying out inox mx3.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;ul&gt;
      &lt;li&gt;Isopropyl.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Something to keep screws organised. Small plastic pots, jar lids etc are good options.&lt;/li&gt;
  &lt;li&gt;A toothpick or similar for applying oil.&lt;/li&gt;
  &lt;li&gt;A cassette tape for testing. A Chrome Type-II type is recommended.&lt;/li&gt;
  &lt;li&gt;A clear space to work. I like to utilise my standing desk and lay down a sheet of card - if someone wants to buy me an anti static mat, both xmas and my birthday are near at the time of writing this ;)&lt;/li&gt;
  &lt;li&gt;Time &amp;amp; patience! This stuff can get fiddly and frustrating, you want enough time to not rush things, and space to be able to leave the unit disassembled and come back to it if you hit a snag.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m noting the ratings of fuses, servo and belts which are from my observations and measurements. I have been unable to find any values for these online and am yet to get hold of a service manual. I would greatly appreciate comments of official values, or your observed values if you are taking a unit apart.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;1x 70mm x 1mm square belt&lt;/li&gt;
  &lt;li&gt;1x 115mm x 4.7mm flat belt&lt;/li&gt;
  &lt;li&gt;1x Sankyo SHU2L 12v motor&lt;/li&gt;
  &lt;li&gt;1x 240v 500mA 20mm fast blow fuse (100v model)&lt;/li&gt;
  &lt;li&gt;1x 240v 120mA 20mm fast blow fuse (240v model)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_1a_tools.JPG&quot; alt=&quot;Gather your tools&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Gather your tools&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_1c_screws.JPG&quot; alt=&quot;Gather your tools&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Keeping fixings tidy saves a headache later on&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;disassembly&quot;&gt;Disassembly&lt;/h2&gt;

&lt;p&gt;Now that we have a space to work and appropriate tools for the job, let’s get into the fun and pull this thing apart.&lt;/p&gt;

&lt;p&gt;The first thing you want to do - which I neglected to photograph - is remove all of the knobs. All knobs, and all mixer sliders will pull off. Some might be a bit sticky but just pull straight up and it will come off. Don’t try to remove the push buttons, they’re affixed from the inside.&lt;/p&gt;

&lt;p&gt;Once the knobs are removed, flip the unit over. Be careful of the exposed knobs, you don’t want to break these (or scratch your desk). I find as long as you lay it down gently you’ll be fine, placing a clean rag (tea towels work well) first is helpful.&lt;/p&gt;

&lt;p&gt;There are 10 screws to remove here. 7 long, 3 short.&lt;/p&gt;

&lt;p&gt;Once those are out, flip it over with the rear facing you. Gently lift the top from the rear. You will find here a ground wire connected to the cassette mechanism. This needs to be removed before lifting the top further. Take the screw out and set it aside. A really nice thing about the mtx units is that the screws are generally all the same, so you can just keep all of these gold screws together.&lt;/p&gt;

&lt;p&gt;Although usually it is obvious where grounding wires connect when putting the mt4x back together, this is where I tend to use a marker. I will usually draw a coloured line across the grounding connection before removal so that it is easy to find the connection point later.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_2b.JPG&quot; alt=&quot;mt4x cassette mechanism grounding wire&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Remove the mechanism grounding wire before opening fully&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With that wire out of the way we can proceed to open the unit. Carefully pivit from the rear to open. There is another ground - this time a pin connector - that you’ll find starting to pull. Slip this off before opening further. You can choose to fully open the unit if you have space, or like me lean the top back against something. Always be careful not to pinch wires or apply too much pressure to connection points.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_3_open.JPG&quot; alt=&quot;mt4x open&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;The open mt4x&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_3b_marking.JPG&quot; alt=&quot;screw marking&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Marking grounding points can prevent later confusion&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With the unit open, lift the shielding layer from the PCB (no need to fully disconnect it), and remove the connections between the top and base. For the grey and blue ribbon connectors there is a black terminal block that can be pulled up to release. The white and red connectors can be pulled straight up. If something feels very stuck, double check what you’re doing before proceeding.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_3a_ribbons.JPG&quot; alt=&quot;Ribbon connectors&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Disconnect the ribbon cables between from base circuit board&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;clean-lube--replace-parts&quot;&gt;Clean, Lube &amp;amp; Replace Parts&lt;/h2&gt;

&lt;p&gt;With the unit top and base seperated, set the top aside somewhere safe, and we will work through servicing the base parts. First take some time to familiarise yourself with what you’ve got in front of you and look for any damage, fluff, signs of past water spills etc. Then before continuing, fit the shield back over the PCB. Have you spotted the fuse yet? It is not the most convenient place, hidden away under the cassette mechanism.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_4_guts_base.JPG&quot; alt=&quot;mt4x guts&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;mt4x base guts exposed&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_4a_guts_base.JPG&quot; alt=&quot;mt4x guts&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Lay the shielding back before continuing work&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_5a_fuse_access.JPG&quot; alt=&quot;mt4x fuse&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;mt4x fuse is located under the cassette mechanism&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_5b_heads.JPG&quot; alt=&quot;mt4x heads&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;A view of the mt4x heads&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With a small brush and tweezers remove any dust and fluff from the cassette mechanism, taking care not to touch the heads at this stage. Once you’ve done this, remove the three remaining screws holding the mechanism in place.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_5c_mechanism.JPG&quot; alt=&quot;mt4x mech&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Remove the three corner screws from the cassette machanism&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Gently flip the mechanism over to the right, resting it upon the shielding.&lt;/p&gt;

&lt;p&gt;From here we have access to the fuse. If it needs replacing, do so now. What a pain to replace a fuse huh!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_5d_fuse_100v.JPG&quot; alt=&quot;mt4x fuse 100v&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Fuse in a 100v model&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_5d_fuse_240v.JPG&quot; alt=&quot;mt4x fuse 240v&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Fuse in a 240v model&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Once again, clean out the exposed area, taking care of any electronic parts.&lt;/p&gt;

&lt;p&gt;Now, there are four small screws holding the cassette mech cover in place. Remove these, carefully setting them aside and ensuring you don’t lose the two plastic latche parts. With this removed you will be able to remove the belts. If they have deteriorated you may need to clean their path in the wheels with a little warm soapy water on a q-tip.&lt;/p&gt;

&lt;p&gt;To oil the servo we need to remove it. There are three screws for this, and once it is out you’ll want to pull the plastic belt wheel off. Give this a clean, and then oil the motor. To oil the motor use a toothpick or similar device rather than trying to apply direct from an oil dispenser. Give a couple of drops into the shaft and then gently rotate it a couple of times. Clean any residue from the exposed shaft before pushing the belt wheel back on, leaving a slight gap between it and the motor body.&lt;/p&gt;

&lt;p&gt;Refix the motor, and then replace the belts (ideally with new ones). Refix the mech cover, being careful not to break the plastic parts.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_7_mech1.JPG&quot; alt=&quot;mt4x mech back&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Back of cassette mechanism&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_7_mech2.JPG&quot; alt=&quot;mt4x mech screws1&quot; class=&quot;img-resize img-center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_7_mech3.JPG&quot; alt=&quot;mt4x mech screws2&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Remove these small screws to expose the belts&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_7a_belts.JPG&quot; alt=&quot;mt4x belts&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;The mt4x belts removed&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_7a_motor1.JPG&quot; alt=&quot;mt4x motor screws&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Remove these screws to remove the motor&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_7c_motor3.JPG&quot; alt=&quot;mt4x motor oil&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Oil the shaft&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_7d_motor4.JPG&quot; alt=&quot;mt4x motor wheel&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Leave a slight gap when refitting&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Refix the cassette machnism in place, and now we will clean the tape heads. Pour a little isopropyl alcohol into a canister, dipping a cotton swab and then using this to gently wide across the heads. If any dirt is visible on the swab tip, flip it over and use the other end until it is clean. I also clean the steel mechanical parts with iso, and the pinch rollers with a little warm, slightly soapy water.&lt;/p&gt;

&lt;p&gt;Now just make sure you’ve cleaned out al the dust and fluff from the base before we start on the top section.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_7e_iso.JPG&quot; alt=&quot;mt4x iso&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Isopropyl and cotton swab for head cleaning&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_7h_mech.JPG&quot; alt=&quot;mt4x mech clean&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Cleaned cassette mechanism and heads&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_7z_brush.JPG&quot; alt=&quot;mt4x brush&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;A cheap paintbrush is a great tool for cleaning&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Set aside the base in a safe place, and pop the top section down in your work space, face down. Lift off the protective shield, but don’t disconnect it. We’re now going to remove all of the PCBs and empty out this section to give it all a good clean.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_8_guts_top.JPG&quot; alt=&quot;mt4x top&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Top section of the unit, ready to be worked on&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There are plastic pins holding in the 1/4” input and RCA jacks. These are two on the inside, and four at the rear of the unit. For those on the rear, there are some you can get to from the inside with a small flathead screwdriver - use this to push them out a bit. From here, and for the rest, I use a plastic opening tool to gently pry these out. Be careful here not to break anything, and pull off the rear plate.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_9_pins1.JPG&quot; alt=&quot;mt4x pins1&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Push the rear plastic pins out a bit using a small screwdriver&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_9_pins2.JPG&quot; alt=&quot;mt4x pins2&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Outer pin removal&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_9_pins3.JPG&quot; alt=&quot;mt4x pins3&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Inner pin removal&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_9b_pins4.JPG&quot; alt=&quot;mt4x pins4&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;One of the inner pins after removal&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With the pins removed, pull this section out. It can be a little tricky, just work it until you find the right angle, and don’t force it. Once you’ve got it loose, disconnect the two ribbon cables. To do this, pull up the plastic outer to loosen and then lift the ribbons straight up.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_10a.JPG&quot; alt=&quot;mt4x ribbons&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Loosen connectors and then lift ribbons straight out&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There is now a series of screws to remove to get these PCBs out. As you do so, gently remove any cables which connect things. Generally these are self-evident as to where they go when reconnecting, but you can always mark connections with a marker as we’ve done earlier. Some screws may be covered by tape. Place all PCBs in a safe place, an antistatic mat is a good choice but I generally just use a wooden dining table.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_10b.JPG&quot; alt=&quot;mt4x pcb_main&quot; class=&quot;img-resize img-center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_10c.JPG&quot; alt=&quot;mt4x pcb2&quot; class=&quot;img-resize img-center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_10d.JPG&quot; alt=&quot;mt4x pcb3&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Three PCBs to remove, as shown here&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now we have an empty shell! There is card lining, leave it in. Pull out the button matrix. Give it all a brush out to remove any fluff etc.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_11_empty.JPG&quot; alt=&quot;mt4x empty_top&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Empty top shell&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_11b.JPG&quot; alt=&quot;mt4x buttons&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Button matrix&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;From here I take it to the bathroom and mix up a small amount of sugar soap with warm water. Using an old toothbrush and a cloth work your way around the unit. Don’t run it under water or get excessive wetness in inside due to the card. Once it’s all pretty clean run over it with a cloth and fresh clean water, then set aside to dry.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_11c_clean.JPG&quot; alt=&quot;mt4x clean_top&quot; class=&quot;img-resize img-center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We now turn our attention to the circuit boards, with their switches and pots. My process is to first remove any large amounts of fluff etc by hand and tweezer. Then use an air can to blow off any loose dust. From here, I use a spray Electrical Clean and Lube with applicator nozzle to each pot and slider, one at a time. Spray, move through a full motion, repeat for each one. As you go through, you’ll find from turning and applying spray that more grime is able to be picked up so remove this as you go.&lt;/p&gt;

&lt;p&gt;For the jacks I spray in some electronic cleaner (not lube) and gently insert a cotton swab to apply some friction to the contacts. Cotton swabs are probably not the best as they can leave cotton behind, but if you’re careful you can avoid this.&lt;/p&gt;

&lt;p&gt;This can be fairly time consuming, just be slow and methodical about it. The results are worth it.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_12a.JPG&quot; alt=&quot;mt4x pcbclean1&quot; class=&quot;img-resize img-center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_13c.JPG&quot; alt=&quot;mt4x pcbclean7&quot; class=&quot;img-resize img-center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_13b.JPG&quot; alt=&quot;mt4x pcbclean6&quot; class=&quot;img-resize img-center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_13d.JPG&quot; alt=&quot;mt4x pcbclean8&quot; class=&quot;img-resize img-center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_12i.JPG&quot; alt=&quot;mt4x pcbclean4&quot; class=&quot;img-resize img-center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_12c.JPG&quot; alt=&quot;mt4x pcbclean2&quot; class=&quot;img-resize img-center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_12k.JPG&quot; alt=&quot;mt4x pcbclean9&quot; class=&quot;img-resize img-center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_12d.JPG&quot; alt=&quot;mt4x pcbclean3&quot; class=&quot;img-resize img-center&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;reassembly&quot;&gt;Reassembly&lt;/h2&gt;

&lt;p&gt;At this stage you will have clean boards, and a clean and dry shell. Now reverse the steps taken to remove everything to put it back together. If ribbon connector pins are a little bent, straighten these before slotting back in. When it comes to the plastic pins squeeze the ends together with some small pliers to insert back into their holes.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_14_pins.JPG&quot; alt=&quot;mt4x pin_attachment&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Squeeze pin ends to insert&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Attach the base to the top, following the order of removal and any markings you made for connectors. When joining the top and botton ensure no cables are pinched.&lt;/p&gt;

&lt;p&gt;Once it’s all together, and before screwing the top and base together or replacing all the knobs, test the unit. Use a guitar, bass or whatever you have at hand with a 1/4” cable and record something to each channel. Then listen back, and rotate all knobs and move sliders. I use headphones. Some of the jacks I haven’t tested at this time such as tape out, but they worked before so I’m fairly happy to test them in the studio later.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_y_testing.JPG&quot; alt=&quot;mt4x testing&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;Testing the unit&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Once you’re happy with it, reattach the knobs and screw the unit together. If all goes well you’ll have a shiny well functioning unit.&lt;/p&gt;

&lt;h2 id=&quot;hit-record&quot;&gt;Hit Record&lt;/h2&gt;

&lt;p&gt;I hope this has been helpful to someone. There are various items I haven’t covered, which I hopefully will at a later date, such as demagnetising, motor speed adjustment and azumith adjustment, but these are often not necessary and a bit more advanced or require more expensive tools.&lt;/p&gt;

&lt;p&gt;I’d love to hear from others with part numbers for these units, and any corrections, questions and ideas in the comments.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-11-29-mt4x/mt4x_z_finished.JPG&quot; alt=&quot;mt4x finished&quot; class=&quot;img-resize img-center&quot; /&gt;
&lt;em&gt;The clean, finished unit&lt;/em&gt;&lt;/p&gt;</content><author><name></name></author><category term="electronics" /><category term="cassette" /><category term="4track" /><category term="audio" /><summary type="html">I’ve recently serviced a couple of Yamaha mt4x four track cassette recorders. Here I overview the process that I took and try to share info that I couldn’t easily find online myself.</summary></entry><entry><title type="html">Mapping the 12 Factor App to Boehm’s Quality Model</title><link href="http://blog.ghostinashell.com/programming/project_management/2020/08/06/boehms-12-factor.html" rel="alternate" type="text/html" title="Mapping the 12 Factor App to Boehm’s Quality Model" /><published>2020-08-06T14:21:00+00:00</published><updated>2020-08-06T14:21:00+00:00</updated><id>http://blog.ghostinashell.com/programming/project_management/2020/08/06/boehms-12-factor</id><content type="html" xml:base="http://blog.ghostinashell.com/programming/project_management/2020/08/06/boehms-12-factor.html">&lt;p&gt;I’ve recently been thinking about the methods of developing computer programs, and have been reading up on some work related to this.&lt;/p&gt;

&lt;p&gt;I quite liked &lt;a href=&quot;https://www.geeksforgeeks.org/boehms-software-quality-model/&quot;&gt;Boehm’s Quality Model&lt;/a&gt;, and thought it’d be interesting to map the &lt;a href=&quot;https://12factor.net/&quot;&gt;12 Factor App methodology&lt;/a&gt; to Boehm’s 7 Quality Factors.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2020-08-07-boehms-12-factor/2020-08-07-boehms-12-factor-1.svg&quot; alt=&quot;12 Factor to Boehm&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I expect I will continue to grow this page over time. The plantuml for this diagram is &lt;a href=&quot;https://github.com/0x646e78/0x646e78.github.io/blob/master/assets/article_images/2020-08-07-boehms-12-factor/2020-08-07-boehms-12-factor-1.puml&quot;&gt;here&lt;/a&gt;&lt;/p&gt;</content><author><name></name></author><category term="programming" /><category term="project_management" /><summary type="html">I’ve recently been thinking about the methods of developing computer programs, and have been reading up on some work related to this.</summary></entry><entry><title type="html">Python set comparisons</title><link href="http://blog.ghostinashell.com/python/2020/06/16/python-set-comparisons.html" rel="alternate" type="text/html" title="Python set comparisons" /><published>2020-06-16T07:15:00+00:00</published><updated>2020-06-16T07:15:00+00:00</updated><id>http://blog.ghostinashell.com/python/2020/06/16/python-set-comparisons</id><content type="html" xml:base="http://blog.ghostinashell.com/python/2020/06/16/python-set-comparisons.html">&lt;p&gt;Today a colleague posted the following code snippet:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;actual = set([&quot;foo&quot;, &quot;bar&quot;] + [&amp;lt;other strings here&amp;gt;])  
expected = set([&quot;bar&quot;, &quot;foo&quot;] + [&amp;lt;other strings here])
if not actual == expected: 
    print(f&quot;Unexpected: {actual - expected}&quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;They were facing the occassional error of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Unexpected: set()&lt;/code&gt; and felt a bit lost.&lt;/p&gt;

&lt;p&gt;After originally thinking about the ordering and edge cases that could affect it somehow to cause the match to be True but also reduce to zero, I came to look at the subtraction and realised that this would happen when when all elements of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;actual&lt;/code&gt; exist within &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;expected&lt;/code&gt;, but &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;expected&lt;/code&gt; also has additional values.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; actual = set([&quot;bar&quot;, &quot;foo&quot;])
&amp;gt;&amp;gt;&amp;gt; expected = set(['foo', 'bar', 'car'])
&amp;gt;&amp;gt;&amp;gt; actual == expected
False
&amp;gt;&amp;gt;&amp;gt; actual - expected
set()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Whereas if that was reversed, you get the additional value within &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;actual&lt;/code&gt;, as it was never subtracted away:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; actual = set(['foo', 'bar', 'car'])
&amp;gt;&amp;gt;&amp;gt; expected = set([&quot;bar&quot;, &quot;foo&quot;])
&amp;gt;&amp;gt;&amp;gt; actual == expected
False
&amp;gt;&amp;gt;&amp;gt; actual - expected
{'car'}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When working with sets, subtraction may not always give you what you think, and so methods have been provided for comparisons. In this case, python provides &lt;a href=&quot;https://docs.python.org/3/library/stdtypes.html#frozenset.difference&quot;&gt;.difference()&lt;/a&gt; and &lt;a href=&quot;https://docs.python.org/3/library/stdtypes.html#frozenset.symmetric_difference&quot;&gt;.symmetric_difference()&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;symmetric_difference()&lt;/code&gt; would be fitting, as it will emit &lt;em&gt;any&lt;/em&gt; item which is not common across both sets. In fact, this is essentially an XOR operation, and python does provide an operator for this - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And so, we could rewrite the comparison with the method:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; actual.symmetric_difference(expected)
{'car'}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;or, using the operator:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; actual ^ expected
{'car'}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We’d then need to identify if the element was in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;actual&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;expected&lt;/code&gt;, but I’ll leave it as an exercise for the reader.&lt;/p&gt;</content><author><name></name></author><category term="python" /><summary type="html">Today a colleague posted the following code snippet:</summary></entry><entry><title type="html">grep mutliple patterns</title><link href="http://blog.ghostinashell.com/linux/bash/grep/til/2020/04/15/TIL-egrep1.html" rel="alternate" type="text/html" title="grep mutliple patterns" /><published>2020-04-15T08:15:00+00:00</published><updated>2020-04-15T08:15:00+00:00</updated><id>http://blog.ghostinashell.com/linux/bash/grep/til/2020/04/15/TIL-egrep1</id><content type="html" xml:base="http://blog.ghostinashell.com/linux/bash/grep/til/2020/04/15/TIL-egrep1.html">&lt;p&gt;We all have habits, and getting things done means that often we don’t look past them, or we’re not exposed to different ways of achieving something. Often I’ll sit back and think “actually let’s find another way of doing this”, or I see a cool trick and want to incororate it into my practice. Too often I don’t pass it on, or don’t practice it.&lt;/p&gt;

&lt;p&gt;And so it goes with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; for me, where I’ve never really looking into multiple matches. So I spent a small chunk of time to work it out.&lt;/p&gt;

&lt;h2 id=&quot;matching-multiple-patterns-using-egrep&quot;&gt;Matching multiple patterns using egrep&lt;/h2&gt;

&lt;p&gt;I had just done one of these:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ kubectl describe nodes|grep Taints
Taints:             &amp;lt;none&amp;gt;
Taints:             &amp;lt;none&amp;gt;
$ kubectl describe nodes|grep Labels
Labels:             beta.kubernetes.io/arch=amd64
Labels:             beta.kubernetes.io/arch=amd64
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I can get the task done using this, and probably in not many more keystrokes, but what if I want these in a one-liner?&lt;/p&gt;

&lt;p&gt;I checked &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man grep&lt;/code&gt; and didn’t see anything obvious, except of course regular expresions, supported when passing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-E&lt;/code&gt; to grep, or otherwise just using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;egrep&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;so when can use:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;egrep '(pattern1|pattern2|patternN)'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Going back to the original multi-grep we can do the following, and improve upon by also matching the Name field:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ kubectl describe nodes | egrep '(^Name|aints|abels)'
Name:               k8smaster
Labels:             beta.kubernetes.io/arch=amd64
Taints:             &amp;lt;none&amp;gt;
Name:               k8sworker1
Labels:             beta.kubernetes.io/arch=amd64
Taints:             &amp;lt;none&amp;gt;`
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;note&lt;/strong&gt; I realised after this that it’s a bad example in practice as thekubectl command could be returning multiple rows of labels if more than one is present, and we’ll only match one. The method of multiple greps is still sound however.&lt;/p&gt;</content><author><name></name></author><category term="linux" /><category term="bash" /><category term="grep" /><category term="til" /><summary type="html">We all have habits, and getting things done means that often we don’t look past them, or we’re not exposed to different ways of achieving something. Often I’ll sit back and think “actually let’s find another way of doing this”, or I see a cool trick and want to incororate it into my practice. Too often I don’t pass it on, or don’t practice it.</summary></entry><entry><title type="html">Ansible Vault key retrieval from Bitwarden</title><link href="http://blog.ghostinashell.com/ansible/2020/03/15/ansible-vault-bitwarden.html" rel="alternate" type="text/html" title="Ansible Vault key retrieval from Bitwarden" /><published>2020-03-15T00:10:00+00:00</published><updated>2020-03-15T00:10:00+00:00</updated><id>http://blog.ghostinashell.com/ansible/2020/03/15/ansible-vault-bitwarden</id><content type="html" xml:base="http://blog.ghostinashell.com/ansible/2020/03/15/ansible-vault-bitwarden.html">&lt;p&gt;I use &lt;a href=&quot;https://bitwarden.com/&quot;&gt;Bitwarden&lt;/a&gt; as my password manager, and I highly recommend it. I also use Ansible a whole lot, and make heavy use of &lt;a href=&quot;https://docs.ansible.com/ansible/latest/user_guide/vault.html&quot;&gt;Ansible Vault&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I’ve recently started using &lt;a href=&quot;http://www.pyinvoke.org/&quot;&gt;Invoke&lt;/a&gt; as my orchestrator after &lt;a href=&quot;https://crgm.net/&quot;&gt;crgm&lt;/a&gt; suggested it, which has got me thinking more about streamlining my processes.
Today I hooked bitwarden into the mix. This is a first pass, but I’m happy with it.&lt;/p&gt;

&lt;p&gt;First up, I installed the &lt;a href=&quot;https://help.bitwarden.com/article/cli/&quot;&gt;bitwarden cli&lt;/a&gt;. See their docs for install and login steps.&lt;/p&gt;

&lt;p&gt;Once that is working and I found that I could retrieve a password, I configured my orchestration.&lt;/p&gt;

&lt;p&gt;You can’t just print the key in the command arguments to ansible-playbook. The available options are to provide a password file (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--vault-password-file&lt;/code&gt;), or to have ansible ask for the key to be typed (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--ask-vault-pass&lt;/code&gt;).
One could probably pipe the key in, but that feels pretty yucky to me, but not as yuck as writing cleartext creds to a file on disk. Fortunately &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--vault-password-file&lt;/code&gt; will also accept an executable that prints the key to stdout.&lt;/p&gt;

&lt;h3 id=&quot;steps&quot;&gt;Steps&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vault-pass.py&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/usr/bin/env python3

import subprocess

def get_vault_key(search='ansible vault key'):
    command = 'bw get password %s' % search
    key = subprocess.run(command.split(), check=True, stdout=subprocess.PIPE)
    return key.stdout.decode('utf-8')

print(get_vault_key())
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It needs to be executable, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chmod u+x vault-pass.py&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Deployment step in invokes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tasks.py&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;from invoke import task

@task
def deploy(c, verbose=False):
    options = ''
    if verbose:
        options += ' -vvv'
    c.run('ansible-playbook play.yml -i inventory --ask-become-pass --vault-password-file vault-pass.py' + options)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now I can run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;invoke deploy&lt;/code&gt; and not have to type the vault key. I want to get rid of the become password next, but will be focusing on moving this approach toward a python module and ansible-runner before then.&lt;/p&gt;</content><author><name></name></author><category term="ansible" /><summary type="html">I use Bitwarden as my password manager, and I highly recommend it. I also use Ansible a whole lot, and make heavy use of Ansible Vault.</summary></entry><entry><title type="html">nftables on Debian 10 with Docker and no iptables</title><link href="http://blog.ghostinashell.com/linux/nftables/2020/03/07/nftables.html" rel="alternate" type="text/html" title="nftables on Debian 10 with Docker and no iptables" /><published>2020-03-07T00:10:00+00:00</published><updated>2020-03-07T00:10:00+00:00</updated><id>http://blog.ghostinashell.com/linux/nftables/2020/03/07/nftables</id><content type="html" xml:base="http://blog.ghostinashell.com/linux/nftables/2020/03/07/nftables.html">&lt;p&gt;I run a Debian 10 system with no iptables, and some multi-container services via docker-compose. 
Dumping some notes here as it can be a real pain.&lt;/p&gt;

&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;/h2&gt;

&lt;p&gt;Install the userspace tools (the kernel modules are already baked in).&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;apt-get install nftables
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To blacklist the iptables module, create &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/modprobe.d/noiptables.conf&lt;/code&gt; with the following:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;install ip_tables /bin/false
install ip6_tables /bin/false
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Start and enable the service:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;systemctl enable nftables.service
systemctl start nftables.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;docker-config&quot;&gt;Docker config&lt;/h2&gt;

&lt;p&gt;In &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/docker/daemon.json&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{
  &quot;iptables&quot;: false
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Previously the flag –iptables=false was used as a systemd override, but this is no longer the case.&lt;/p&gt;

&lt;p&gt;In &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/systemd/system/docker.service.d/override.conf&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --fixed-cidr=172.17.0.0/16
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This sets a static range &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;172.17.0.0/16&lt;/code&gt; for the docker network. If you haven’t used systemd overrides before, the blank &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExecStart=&lt;/code&gt; is needed to clear the value before applying a new one.&lt;/p&gt;

&lt;p&gt;Then we restart docker:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;systemctl daemon-reload
systemctl restart docker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;fuck you docker…. (docker-ce will always install iptables userspace tools as a dependency)&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# apt-get remove iptables
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following packages were automatically installed and are no longer required:
  aufs-dkms aufs-tools cgroupfs-mount dkms libltdl7 linux-headers-amd64
Use 'apt autoremove' to remove them.
The following packages will be REMOVED:
  docker-ce iptables
0 upgraded, 0 newly installed, 2 to remove and 5 not upgraded.
After this operation, 112 MB disk space will be freed.
Do you want to continue? [Y/n] n
Abort.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and so&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ln -s /sbin/iptables-nft /local/sbin/iptables
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;nftables-rules&quot;&gt;nftables rules&lt;/h2&gt;

&lt;p&gt;A fairly simple config that works for me so far.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/nftables.conf&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/usr/sbin/nft -f

#whitelist IPs
define home = xxx.xxx.xxx.xxx
define work = xxx.xxx.xxx.xxx
#internal IPs
define docker_ipv4 = 172.17.0.0/16

flush ruleset

table inet filter {
  set whitelist_ips {
    type ipv4_addr
    flags constant, interval
    elements = { $home, $work }
  }
  chain base_checks {
    ct state {established, related} accept
    ct state invalid drop
  }
  chain input {
    type filter hook input priority 0; policy drop;
    jump base_checks
    iifname lo accept
    ip saddr $docker_ipv4 accept
    ip saddr != @whitelist_ips drop
    ip protocol icmp accept
    tcp dport ssh accept
    tcp dport https accept
    drop
  }
  chain forward {
    type filter hook forward priority 0; policy drop;
    ct state {established,related} accept
    ip saddr $docker_ipv4 oif eth0 accept
    ip saddr $docker_ipv4 oifname &quot;br-*&quot; accept
  }
  chain output {
    type filter hook output priority 0; policy accept;
  }
}
table ip nat {
  chain prerouting {
    type nat hook prerouting priority 0;
  }
  chain postrouting {
    type nat hook postrouting priority 100;
    ip saddr $docker_ipv4 oif eth0 masquerade
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This allows forwarding between docker interfaces and to eth0, NAT to the container network, and a filtered input.&lt;/p&gt;

&lt;p&gt;Load up the new rules with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemctl reload nftables&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&quot;logging&quot;&gt;Logging&lt;/h2&gt;

&lt;p&gt;nftables service logs can be viewed from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;journalctl --unit=nftables.service&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Logging of rules can be set up such as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ip saddr &amp;lt;someaddress&amp;gt; log prefix &quot;Some Prefix: &quot; accept
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;reference-material&quot;&gt;Reference Material&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://wiki.nftables.org/wiki-nftables/index.php/Main_Page&quot;&gt;nftables wiki&lt;/a&gt;&lt;/p&gt;</content><author><name></name></author><category term="linux" /><category term="nftables" /><summary type="html">I run a Debian 10 system with no iptables, and some multi-container services via docker-compose. Dumping some notes here as it can be a real pain.</summary></entry><entry><title type="html">Using Conftest to enforce Terraform allowed resources</title><link href="http://blog.ghostinashell.com/security/2019/11/21/conftest-terraform-whitelist.html" rel="alternate" type="text/html" title="Using Conftest to enforce Terraform allowed resources" /><published>2019-11-21T10:10:00+00:00</published><updated>2019-11-21T10:10:00+00:00</updated><id>http://blog.ghostinashell.com/security/2019/11/21/conftest-terraform-whitelist</id><content type="html" xml:base="http://blog.ghostinashell.com/security/2019/11/21/conftest-terraform-whitelist.html">&lt;p&gt;I’ve just been playing with &lt;a href=&quot;https://github.com/instrumenta/conftest&quot;&gt;conftest&lt;/a&gt;
 as a means to enforce a whitelist of allowed Terraform resources. Conftest &lt;em&gt;“is
  a utility to help you write tests against structured configuration data”&lt;/em&gt; and
  uses the Open Policy Agent rego syntax.&lt;/p&gt;

&lt;p&gt;The setup that I’m working with is a controlled CI environment, where agents 
run a docker build container which hosts the underlying build tools - such as
terraform, aws cli etc.  Makefiles are provided in this image also, which are
included in a projects build. We use Cloudformation for deployment of AWS
resources, and there is concern that people will start to use terraform for these,
which we want to discourage and possibly prevent.&lt;/p&gt;

&lt;p&gt;After playing for the afternoon I got to an OK point with this. There are of
course issues - as the person running a build can insert abitrary commands in
their build steps they could call terraform direct to bypass my current
way of doing this - and so it is currently more of a helpful check than a strict
policy enforcement, but I’m sure this could be addressed when I spend some more
time on it.&lt;/p&gt;

&lt;h3 id=&quot;in-the-build-agent&quot;&gt;In the build agent:&lt;/h3&gt;

&lt;p&gt;First install Terrraform and Conftest, and then set the following configuration.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;/opt/policy/terraform/base.rego&lt;/em&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;package main

whitelist = [
  &quot;datadog&quot;,
  &quot;pagerduty&quot;
]

deny[msg] {
  resources := input.resource_changes[_].type
  not check_resources(resources, whitelist)
  allowed := concat(&quot;, &quot;, whitelist)
  msg = sprintf(&quot;Terraform plan will change prohibited resources which are not in the following namespaces: %v&quot;, [allowed])
}

# Checks whether the plan will cause resources with certain prefixes to change
check_resources(resource, allowed_prefixes) {
  startswith(resource, allowed_prefixes[_])
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;/opt/make/terraform.mk&lt;/em&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
tf-init: ##Init state and vars
	@terraform init

tf-plan: tf-init ##Validate and check for changes
	@terraform version &amp;amp;&amp;amp; \
	terraform validate &amp;amp;&amp;amp; \
	terraform plan -out /tmp/plan.tf

tf-conftest: tf-plan ##Check the validation with conftest
	@terraform show -json /tmp/plan.tf | conftest -p /opt/policy/terraform/ test -

tf-clean: ##Remove files created during make
	@rm -f /tmp/plan.tf

tf-apply: tf-init tf-plan tf-conftest tf-clean ##Apply changes
	@terraform apply -auto-approve
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;and-now-in-a-project&quot;&gt;And now in a project:&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Makefile&lt;/em&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;include /opt/make/terraform.mk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;in your build steps&lt;/em&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;make tf-plan tf-conftest

#Release to prod
make tf-apply
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now when a build is run, conftest checks the terraform plan against it’s
policy and if a resource has been defined which isn’t in the 
whitelist, the build will fail.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;...
...
Terraform will perform the following actions:

  # aws_ebs_volume.example will be created
  + resource &quot;aws_ebs_volume&quot; &quot;example&quot; {
      + arn               = (known after apply)
      + availability_zone = &quot;us-east-2a&quot;
      + encrypted         = (known after apply)
      + id                = (known after apply)
      + iops              = (known after apply)
      + kms_key_id        = (known after apply)
      + size              = 10
      + snapshot_id       = (known after apply)
      + tags              = {
          + &quot;Name&quot; = &quot;ConfTestTest&quot;
        }
      + type              = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

------------------------------------------------------------------------


FAIL - Terraform plan will change prohibited resources which are not in the following namespaces: datadog, pagerduty
make: *** [/opt/make/terraform.mk:20: tf-conftest] Error 1

$ 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name></name></author><category term="security" /><summary type="html">I’ve just been playing with conftest as a means to enforce a whitelist of allowed Terraform resources. Conftest “is a utility to help you write tests against structured configuration data” and uses the Open Policy Agent rego syntax.</summary></entry></feed>