<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://feeney.mba/feed.xml" rel="self" type="application/atom+xml" /><link href="https://feeney.mba/" rel="alternate" type="text/html" hreflang="en-US" /><updated>2026-03-04T01:51:01+00:00</updated><id>https://feeney.mba/feed.xml</id><title type="html">Sean Feeney - Silicon Desert Trailblazer</title><subtitle>Sean Feeney is a transformational Silicon Desert leader.</subtitle><author><name>Sean Feeney</name></author><entry><title type="html">Fix Ink Smears When Printing on Epson EcoTank Printer (2025)</title><link href="https://feeney.mba/fix-ink-smears-when-printing-on-epson-ecotank-printer-(2025).html" rel="alternate" type="text/html" title="Fix Ink Smears When Printing on Epson EcoTank Printer (2025)" /><published>2025-11-30T21:18:27+00:00</published><updated>2025-11-30T21:18:27+00:00</updated><id>https://feeney.mba/fix-ink-smears-when-printing-on-epson-ecotank-printer-(2025)</id><content type="html" xml:base="https://feeney.mba/fix-ink-smears-when-printing-on-epson-ecotank-printer-(2025).html"><![CDATA[<p>If you notice smearing when printing, for example, a block with a lot of black ink, your Epson printer settings need to be adjusted. First, if you have not yet done so, install the Epson drivers for your printer so that you get the specialized Printer Properties dialog. Now open the thing you’re trying to print and click Printer Properties (or something similar).</p>

<p><img src="/assets/img/2025/epson1.png" alt="" /></p>

<p>In the Printer Properties, click the Maintenance tab.</p>

<p><img src="/assets/img/2025/epson2.png" alt="" /></p>

<p>Click Extended Settings</p>

<p><img src="/assets/img/2025/epson3.png" alt="" /></p>

<p>Check the second box “Check Paper Width Before Printing” and click OK. Click OK again to exit the Printer Properties dialog. Now you should be able to print without smearing. If not, you may also need to adjust the preset from standard to high quality to slow the print, on the first tab of the Printer Properties dialog.</p>

<p>This was targeted at my Costco special ET-3850 on Windows, but should work for other Epson printers and other OS with minor adjustments.</p>]]></content><author><name>Sean Feeney</name></author><category term="printers" /><summary type="html"><![CDATA[Fix Ink Smears When Printing on Epson EcoTank Printer (2025)]]></summary></entry><entry><title type="html">Unable to write chat.mcp.access because it is configured in system policy.</title><link href="https://feeney.mba/unable-to-write-chat.mcp.access-because-it-is-configured-in-system-policy/html" rel="alternate" type="text/html" title="Unable to write chat.mcp.access because it is configured in system policy." /><published>2025-09-30T15:58:36+00:00</published><updated>2025-09-30T15:58:36+00:00</updated><id>https://feeney.mba/unable-to-write-chat.mcp.access-because-it-is-configured-in-system-policy/unable-to-write-chat.mcp.access-because-it-is-configured-in-system-policy.</id><content type="html" xml:base="https://feeney.mba/unable-to-write-chat.mcp.access-because-it-is-configured-in-system-policy/html"><![CDATA[<p>If your users are receiving VSCode error message “Unable to write chat.mcp.access because it is configured in system policy.” it may be related to an out-of-date VSCode (see bug report <a href="https://github.com/microsoft/vscode/issues/246585">here</a>). If they still receive it after updating, try enabling this setting at the org or enterprise level:</p>

<p><strong>MCP servers in Copilot</strong></p>

<p>If enabled, users can configure Model Context Protocol (MCP) servers (including third-party servers) for Copilot in all Copilot editors and Coding Agent.</p>]]></content><author><name>Sean Feeney</name></author><category term="Microsoft" /><category term="AI" /><summary type="html"><![CDATA[How to fix VSCode error "Unable to write chat.mcp.access because it is configured in system policy."]]></summary></entry><entry><title type="html">Can’t Login to Windows 11 Without Internet</title><link href="https://feeney.mba/can't-login-to-windows-11-without-internet.html" rel="alternate" type="text/html" title="Can’t Login to Windows 11 Without Internet" /><published>2025-03-28T00:49:55+00:00</published><updated>2025-03-28T00:49:55+00:00</updated><id>https://feeney.mba/can&apos;t-login-to-windows-11-without-internet</id><content type="html" xml:base="https://feeney.mba/can&apos;t-login-to-windows-11-without-internet.html"><![CDATA[<p>Sometimes Windows 11 can get into a state where it claims you can’t log in with your PIN while the Internet is down, even though the PIN is correct. It doesn’t offer to failback to password even though the PIN is theoretically linked to your password.</p>

<p>This problem corresponds to a new GUI setting called “For improved security, only allow Windows Hello sign-in for Microsoft accounts on this device (recommended)” in Accounts &gt; Sign-in options &gt; Additional settings. If you can log in with some other administrator account, this is the setting to change. If you can’t, here’s how you disable it via Recovery:</p>

<p>Start your PC and on the login screen click the Power button at the bottom right, then press Shift and click Restart. That will boot your PC into the Recovery Environment.</p>

<p>Here, choose Troubleshoot, then Advanced Options, then Command Prompt.</p>

<p>Run this command to disable the option “Require Windows Hello Sign In for Microsoft Accounts”:</p>

<p>reg add “HKLM\SOFTWARE\Microsoft\PolicyManager\default\Settings\AllowSignInOptions” /v value /t REG_DWORD /d 0 /f</p>

<p>Type exit and hit enter</p>

<p>Select Continue to reboot into normal Windows. You should now be able to sign in with the PIN while offline.</p>]]></content><author><name>Sean Feeney</name></author><category term="Windows" /><summary type="html"><![CDATA[If your Internet is down and it's blocking your Windows Hello PIN, this post is for you.]]></summary></entry><entry><title type="html">A History of BGS Flip Types</title><link href="https://feeney.mba/a-history-of-bgs-flip-types.html" rel="alternate" type="text/html" title="A History of BGS Flip Types" /><published>2024-03-06T02:12:49+00:00</published><updated>2024-03-06T02:12:49+00:00</updated><id>https://feeney.mba/a-history-of-bgs-flip-types</id><content type="html" xml:base="https://feeney.mba/a-history-of-bgs-flip-types.html"><![CDATA[<p>Beckett, an established player in the cards market thanks to their monthly price guide magazines, began offering card grading services in 1999. It has experimented with several lines of business, such as:</p>

<table>
  <thead>
    <tr>
      <th style="text-align: center">Beckett Grading Services (BGS)</th>
      <th style="text-align: center">Beckett Vintage Grading (BVG)</th>
      <th style="text-align: center">Beckett Authentication Services (BAS)</th>
      <th style="text-align: center">Beckett Collector Club Grading (BCCG)</th>
      <th style="text-align: center">Beckett Raw Card Review</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: center"><img src="/assets/img/assets/img/bgs.png" alt="" /></td>
      <td style="text-align: center"><img src="/assets/img/assets/img/bvg.png" alt="" /></td>
      <td style="text-align: center"><img src="/assets/img/assets/img/bas.png" alt="" /></td>
      <td style="text-align: center"><img src="/assets/img/assets/img/bccg.png" alt="" /></td>
      <td style="text-align: center"><img src="/assets/img/assets/img/raw.png" alt="" width="150" /></td>
    </tr>
    <tr>
      <td style="text-align: center">Their most well-known offering, for cards from 1981-present.</td>
      <td style="text-align: center">For vintage cards pre-1981. Black labels are not available.</td>
      <td style="text-align: center">For aftermarket autographs. There is a sticker version, a slabbed version, and a quick opinion “<a href="https://www.beckett-authentication.com/services/signature-review">Signature Review</a>.”</td>
      <td style="text-align: center">A lower tier option offered from the early 2000s to 2023.</td>
      <td style="text-align: center">A sticker version available at card shows.</td>
    </tr>
  </tbody>
</table>

<p>Beckett offers one of the few autograph grading features in the graded card world, whereas competitors tend to only offer autograph authentication services. It was first to market with subgrades for centering, corners, edges, and surface, and possibly for overall half-point grades period.</p>

<p>Beckett has also added VHS and comic/manga/magazine grading (CBCS) with slabs that look very different. For this article, we will focus only on their BGS line of business.</p>

<p>A “flip” refers to the label on a slab as well as the slab itself, in terms of style, color, and other attributes. For BGS label colors and material, traditionally a grade 9.5 - 10 is gold, 8.5 - 9 is silver, and anything below is white (with a paper label instead of metal). Since 2014, a perfect 10 in all subgrades gets a black metal label. In 2023, the white paper labels were phased out and everything below 9.5 started getting silver metal labels.</p>

<p>There are also “<a href="https://www.comc.com/Cards,sr,+-auto,ot,aGraded,rBGS,gEncased,i100">encased</a>” non-graded versions of BGS slabs with gold, silver, or even green metal labels where the colors don’t seem to mean anything. I’ve seen them with a Leaf logo, a “Beckett Grading” logo, and no logo on the front label.</p>

<p>BGS Flip Type #1 – Issued from 1999 to 2016, this is the original design. At some point, they added the Beckett logo to the back of the autograph grade square. Ungraded encased sometimes have (relic?) swatches where the autograph grade square would go. At some point in the 2000s, Beckett partnered with a company called GGUM to specifically insert game-used memorabilia this way on graded cards, but those can be identified by the GGUM logo on the back of the label. The provenance of the swatches embedded after GGUM went out of business is unclear. Some <a href="https://forums.collectors.com/discussion/comment/7680218/#Comment_7680218">forum posts</a> suggest folks could get self-provided jersey swatches included.</p>

<p><img src="/assets/img/assets/img/bgsOld1.png" alt="" width="400" /></p>

<p>BGS Flip Type #2 – Issued from mid-2016 to present, they simplified their slab design with fewer notches and incorporated an etched logo into the slab corner. The autograph grade moved to the back of the label, and subgrading became an optional extra. It can stack with the original slabs but is slightly smaller overall. A patent number is visible at the bottom – and for a while was <a href="https://www.sportscardradio.com/beware-fake-bgs-graded-slabs/">a way to identify fakes</a> in addition to label font and spacing.</p>

<p><img src="/assets/img/assets/img/bgsCurrent1.png" alt="" width="400" /> <img src="/assets/img/assets/img/bgsCurrent2.jpg" alt="" width="400" /></p>

<p>Sources:</p>

<ul>
  <li><a href="https://www.amazon.com/ask/answer/Mx15RPJ2W0ZQUYT/">Superior-Sports-Investments</a></li>
  <li><a href="https://allvintagecards.com/beckett-card-grading-guide/">Beckett Card Grading (A Collector’s Guide)</a></li>
  <li><a href="https://diamondelitecards.com/everything-you-need-to-know-about-bgs-black-label-10-grades/">Everything You Need to Know About BGS Black Label 10 Grades</a></li>
  <li><a href="https://rjtriestocollect.medium.com/what-is-ggumcard-81e63423652f">What is GGUMCARD?</a></li>
  <li><a href="https://www.beckett.com/news/beckett-grading-launches-new-single-grade-service/">Beckett Grading Launches New Single Grade Service</a></li>
  <li><a href="https://www.beckett.com/grading/about">Beckett</a></li>
</ul>]]></content><author><name>Sean Feeney</name></author><summary type="html"><![CDATA[Beckett Graded Slab Flip Types]]></summary></entry><entry><title type="html">A History of SGC Flip Types</title><link href="https://feeney.mba/a-history-of-sgc-flip-types.html" rel="alternate" type="text/html" title="A History of SGC Flip Types" /><published>2024-03-03T19:27:33+00:00</published><updated>2024-03-03T19:27:33+00:00</updated><id>https://feeney.mba/a-history-of-sgc-flip-types</id><content type="html" xml:base="https://feeney.mba/a-history-of-sgc-flip-types.html"><![CDATA[<p>SGC (Sportscard Guaranty LLC) is the third-largest trading card grading company behind PSA and CSG. SGC was founded in 1998, and like its biggest competitor, has changed its flip several times since then. A “flip” refers to the label on a slab as well as the slab itself, in terms of style, color, and other attributes.</p>

<p>SGC Flip Type #1 – Issued from 1998 to mid-1999, this is the original design. It utilized a 100-point grading scale.</p>

<p><img src="/assets/img/assets/img/SGC-Old-Label-98-Score-Gem-Mint.png" alt="" width="400" /></p>

<p>SGC Flip Type #2 – Issued from 1999 - 2000, this transitional flip has the future green label color and Sportscard Guaranty, LLC lettering rising out of the back of the slab. They temporarily dropped barcodes.</p>

<p><img src="/assets/img/assets/img/sgc-type2.png" alt="" width="400" /></p>

<p>SGC Flip Type #3 – Issued from 2000 - 2018, this flip added the URL to the label and a gold hologram on the back of the label. The label border was green until 2017, when a perfect 100 score began getting a gold border instead.</p>

<p><img src="/assets/img/assets/img/sgc-type3.png" alt="" width="400" /></p>

<p>SGC Flip Type #4 – Issued from 2018 - present, SGC switched to a 10-point grading scale (with possible half points) and the label border changed to black (except for perfect 10s, which remained gold). Instead of a gold hologram on the back, SGC lettering rises out of the back of the slab, similar to Type #2.</p>

<p><img src="/assets/img/assets/img/sgc-modern.png" alt="" width="400" /></p>

<p>In 2024, SGC was acquired by Collectors Holdings, the owner of PSA.</p>

<p>Sources:</p>

<ul>
  <li><a href="https://forums.collectors.com/discussion/comment/8423438/#Comment_8423438">otwcards</a></li>
  <li><a href="https://onlygreats.com/2023/09/15/sgc-gold-label/">SGC Gold Label</a></li>
</ul>]]></content><author><name>Sean Feeney</name></author><category term="baseball cards" /><summary type="html"><![CDATA[Sportscard Guaranty Graded Slab Flip Types]]></summary></entry><entry><title type="html">AmazonSSMDirectoryServiceInstanceProfileRole</title><link href="https://feeney.mba/amazonssmdirectoryserviceinstanceprofilerole.html" rel="alternate" type="text/html" title="AmazonSSMDirectoryServiceInstanceProfileRole" /><published>2023-09-05T22:11:55+00:00</published><updated>2023-09-05T22:11:55+00:00</updated><id>https://feeney.mba/amazonssmdirectoryserviceinstanceprofilerole</id><content type="html" xml:base="https://feeney.mba/amazonssmdirectoryserviceinstanceprofilerole.html"><![CDATA[<p>If you try to launch a Directory Service administration EC2 instance, it takes you to a page with some input parameters. One of them says: “IAM instance profile name. By Default, if no instance profile exists with the name AmazonSSMDirectoryServiceInstanceProfileRole, an instance profile with the name AmazonSSMDirectoryServiceInstanceProfileRole will be created.”<br />
<br />
However, depending on your environment, you might not be able to let it create this on your behalf, in which case you need to create it manually or offer an alternative role with equivalent permissions. Googling this role name finds no AWS documentation about it, but you can inspect the associated SSM Document (<a href="https://us-east-1.console.aws.amazon.com/systems-manager/documents/AWS-CreateDSManagementInstance/description?region=us-east-1">AWS-CreateDSManagementInstance</a>) and you’ll find that it requires two managed policies AmazonSSMManagedInstanceCore and AmazonSSMDirectoryServiceAccess, and an AssumeRole trust relationship to ec2.amazonaws.com. SSM Documents are not fun to wade through, so hopefully this helps someone else out there save some time.</p>]]></content><author><name>Sean Feeney</name></author><category term="AWS" /><summary type="html"><![CDATA[What is the AmazonSSMDirectoryServiceInstanceProfileRole role?]]></summary></entry><entry><title type="html">Why does your build pipeline fail even though there were no changes?</title><link href="https://feeney.mba/Why-does-your-build-pipeline-fail-even-though-there-no-changes.html" rel="alternate" type="text/html" title="Why does your build pipeline fail even though there were no changes?" /><published>2023-08-11T01:03:15+00:00</published><updated>2023-08-11T01:03:15+00:00</updated><id>https://feeney.mba/Why-does-your-build-pipeline-fail-even-though-there-no-changes</id><content type="html" xml:base="https://feeney.mba/Why-does-your-build-pipeline-fail-even-though-there-no-changes.html"><![CDATA[<blockquote>
  <p>I didn’t change anything! Why is my pipeline failing!?</p>
</blockquote>

<p>is a common cry of the average developer. It is often said that 80% of tech failures are due to changes<sup>[<a href="https://wikisummaries.org/visible-ops/" title="source">source</a>]</sup>. CI/CD pipelines are particularly tricky, lending themselves towards <a href="https://en.wikipedia.org/wiki/Software_rot" title="dependency rot">dependency rot</a> if not actively updated and maintained. Pipeline runs can fail for a variety of reasons. Let’s look at the top five most common failures, and what you can do about it.</p>

<ol>
  <li><strong>You actually did change something</strong> - hence why you’re running the pipeline. The most common cause of pipeline failures are your software code. I know, it hurts, but that’s all you changed, right?
    <ul>
      <li>What you can do about it: Test the failing pipeline step locally to see if you can replicate the issue. You may need to add verbosity, print statements, etc. until you find the exact line(s) of code responsible.</li>
    </ul>
  </li>
  <li><strong>You didn’t bring your dependencies in-house and/or pin their versions</strong>. The next most common cause of unexpected pipeline failure is poor dependency management. Many enterprises were caught off guard in 2016 when a little-known open-source npm package, left-pad, was removed from the npm registry by its author. “Most programmers had never heard of left-pad, but now, somehow, their code couldn’t run without it.”<sup>[<a href="https://qz.com/646467/how-one-programmer-broke-the-internet-by-deleting-a-tiny-piece-of-code" title="source">source</a>]</sup> React and numerous other popular packages could no longer build. They were all bit by this same issue you’re now running into!
    <ul>
      <li>What you can do about it:
        <ul>
          <li>Never reference a public repo in your private pipeline. Nothing should ever be directly downloaded over the public Internet during your pipeline run. Instead, leverage a binary repository (e.g. GitHub Packages, Artifactory, or Nexus) that can proxy your external dependencies and cache them within your network. In addition to avoiding issues like left-pad in public repos, and Internet connection or firewall failures, this can increase security as common public packages are often targeted with malware, and the binary repositories can scan them and build SBOMs with them.</li>
          <li>Never use “latest.” I know, this can be tempting. I always want my dependencies to be up to date, and “latest” is how you get there, right? Unfortunately, this can lead to unexpected and breaking changes. There is no commonly agreed-upon definition of what a minor and major upgrade is, and there’s no guarantee that future versions will offer the same functionality - with the same interface - as the current version. You need to fully test each version upgrade, preferably one dependency at a time, and the middle of your software change isn’t necessarily the best time to do so. Prevent the unexpected by pinning to a specific version of your dependency.</li>
        </ul>
      </li>
    </ul>
  </li>
  <li><strong>Patching - or not patching - your base image</strong>. Modern CI/CD pipelines run each step in its own container, passing only the filesystem and environmental variables along from step to step. Whether you realize it or not, you’re choosing the operating system (OS), patch level, and configuration of that container and it can suffer from the same pinned version issues as mentioned above. Alpine was a popular lightweight container in the early days of containers, but it was thin because it shed some lessons hard learned by other Linux OS. Older Alpine versions can suffer from network bugs in certain environments - even if previous runs didn’t encounter issues! This is but one example of many OS issues that can creep in over the course of time.
    <ul>
      <li>What you can do about it: Pay close attention to your base image choices - and any layers you add to them - and regularly update them for security and operational reasons. Once per month is a good cadence. Fully test your pipeline after updating the image(s), even if you don’t have a scheduled software release. Look for keywords in your pipeline(s) like <code class="language-plaintext highlighter-rouge">image:</code>, <code class="language-plaintext highlighter-rouge">FROM</code>, or <code class="language-plaintext highlighter-rouge">container:</code> to determine what image(s) you’re using.</li>
    </ul>
  </li>
  <li><strong>Trusting shared actions, workflows, or jobs</strong>. Some CI/CD software have marketplaces where you can find one-liners that you can add to your pipeline and it seems like magic happens. These are abstractions, and they do make your pipeline look cleaner. But they can suffer from the issues mentioned above, with no SLA of when, if ever, an issue encountered might be fixed as <a href="https://gist.github.com/richhickey/1563cddea1002958f96e7ba9519972d9">open-source authors do not owe you support</a>.
    <ul>
      <li>What you can do about it: Balance your usage of these shared components with the amount of time you can allot to building out your pipeline, realizing that any time saved upfront may be lost later if and when a blocking issue occurs. Where possible, pin to a specific version and download its source code into your own network in case the author chooses to delete it or radically change it in the future. Most importantly, seek to understand what the abstraction is doing for you - even if only at a high level - so that you can troubleshoot it when the time comes.</li>
    </ul>
  </li>
  <li><strong>Not configuring your build tools properly</strong>. As the layers of virtualization and the number of tools increases, so does the number of configuration switches you may have to set for each. As mentioned earlier, each step in your pipeline runs in its own container. That container can have OS settings that need to be tuned. If you use a JVM-hosted language, you’ve definitely got some settings to optimize there. If you use a compiled language, that compiler is going to have some settings. Each package manager you use may have some necessary settings (at the very least, to point to and prioritize your private repo). ARM is growing in popularity, so you may have to target it, or alternatively specify that you want x86 (or some other vendor-specific architecture). And that’s not even getting into all the potential test tools you may have!
    <ul>
      <li>What you can do about it: Accepting the default settings is okay, until it’s not. Just because your build worked with them in the past doesn’t mean it will always work with them. More code, more build and test tools, more performance challenges. New security tooling or patching stealing more CPU time from the runner VM. Some of that can be out of your control. But tuning every part of your pipeline to its fullest is within your control, and if you still encounter resource issues, consider leveraging a larger runner.</li>
    </ul>
  </li>
</ol>]]></content><author><name>Sean Feeney</name></author><category term="software engineering" /><category term="DevOps" /><category term="Development Platforms" /><category term="CI/CD" /><summary type="html"><![CDATA[Common causes of CI/CD pipeline failures]]></summary></entry><entry><title type="html">IAM Roles Required for AWS Resilience Hub</title><link href="https://feeney.mba/awsResilienceHubIAMPermissions.html" rel="alternate" type="text/html" title="IAM Roles Required for AWS Resilience Hub" /><published>2023-01-24T01:07:00+00:00</published><updated>2023-01-24T01:07:00+00:00</updated><id>https://feeney.mba/awsResilienceHubIAMPermissions</id><content type="html" xml:base="https://feeney.mba/awsResilienceHubIAMPermissions.html"><![CDATA[<p>AWS announced GA of Resilience Hub at re:Invent ‘21. However, it went GA without support for service-linked roles, and the service doesn’t have a console button for creating the IAM roles it needs like some of the other new services do. The only documentation is <a href="https://docs.aws.amazon.com/resilience-hub/latest/userguide/security-iam-resilience-hub-permissions.html" title="AWS Resilience Hub permissions reference">here</a> and it’s not entirely clear. So I’ve written some Terraform to take care of this for you. You may need to modify it if your scenario differs.</p>

<p>The scenario: Multi-account architecture with IAM Identity Center (SSO). The users of a specific SSO permissions set will log in and point Resilience Hub at Terraform state files. The state files are generally centrally stored in S3, but the Terraform might deploy infra into any account within the AWS Organization. Also, there are a few accounts they might try and run this from.</p>

<p>If you use permissions boundaries to limit the reach of permissions sets, you need to either exclude these Resilience Hub roles from the boundary enforcement or add the boundary to them.</p>

<p>In the SSO permission set(s), allow the users to assume the <code class="language-plaintext highlighter-rouge">AwsResilienceHubAdminAccountRole</code> in each account they might run Resilience Hub from:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>{
    "Effect": "Allow",
    "Action": [
      "iam:GetRole",
      "iam:PassRole",
      "sts:AssumeRole"
    ],
    "Resource": [
      "arn:aws:iam::&lt;account1ID&gt;:role/AwsResilienceHubAdminAccountRole",
      "arn:aws:iam::&lt;account2ID&gt;:role/AwsResilienceHubAdminAccountRole",
      "arn:aws:iam::&lt;account3ID&gt;:role/AwsResilienceHubAdminAccountRole"
    ]
  }
</code></pre></div></div>

<p>Create the <code class="language-plaintext highlighter-rouge">AwsResilienceHubAdminAccountRole</code>, <code class="language-plaintext highlighter-rouge">AwsResilienceHubExecutorAccountRole</code>, and <code class="language-plaintext highlighter-rouge">AwsResilienceHubPeriodicAssessmentRole</code> IAM roles in the target accounts. The Admin role is required in the account Resilience Hub is run from, and the Executor and Periodic roles are required in each account the Terraform state file(s) build(s) in. It doesn’t hurt if they all exist in every account. The variable is the account ID number you’re deploying the roles into.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>variable "aws_account_id" {
  type = string
}

terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
    }
  }
}

data "aws_iam_roles" "ssoRole" {
  name_regex = "AWSReservedSSO_&lt;SSOPermissionSetName&gt;_.*"
}

resource "aws_iam_role" "AwsResilienceHubAdminAccountRole" {
  name = "AwsResilienceHubAdminAccountRole"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          AWS = "arn:aws:iam::${var.aws_account_id}:root"
        }
      },
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          AWS = data.aws_iam_roles.ssoRole.arns
        }
      },
    ]
  })

  inline_policy {
    name = "AwsResilienceHubAdminAccountRole_policy"
    
    policy = jsonencode({
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "sts:AssumeRole"
                ],
                # Wildcards aren't the best, hardcode all your account numbers to increase security
                "Resource": "arn:aws:iam::*:role/AwsResilienceHubExecutorAccountRole"
            },
        ]
    })
  }
}

resource "aws_iam_role" "AwsResilienceHubExecutorAccountRole" {
  name = "AwsResilienceHubExecutorAccountRole"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          AWS = [
            # IAM appears to validate these, so they must exist first
            "arn:aws:iam::&lt;account1ID&gt;:role/AwsResilienceHubAdminAccountRole",
            "arn:aws:iam::&lt;account2ID&gt;:role/AwsResilienceHubAdminAccountRole",
            "arn:aws:iam::&lt;account3ID&gt;:role/AwsResilienceHubAdminAccountRole"
          ]
        }
      },
    ]
  })

  depends_on = [aws_iam_role.AwsResilienceHubAdminAccountRole]

  inline_policy {
    name = "AwsResilienceHubExecutorAccountRole_policy"
    
    policy = jsonencode({
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "resiliencehub:*"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "ssm:DescribeAutomationExecutions"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "sns:GetTopicAttributes",
                    "sns:ListSubscriptionsByTopic",
                    "sns:GetSubscriptionAttributes"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "cloudformation:DescribeStacks",
                    "cloudformation:ListStackResources",
                    "cloudformation:ValidateTemplate"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "servicecatalog:GetApplication",
                    "servicecatalog:ListAssociatedResources"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "resource-groups:ListGroupResources",
                    "resource-groups:GetGroup",
                    "tag:GetResources"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "cloudwatch:DescribeAlarms",
                    "cloudwatch:GetMetricData",
                    "cloudwatch:GetMetricStatistics",
                    "cloudwatch:PutMetricData"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "fis:GetExperimentTemplate",
                    "fis:ListExperimentTemplates",
                    "fis:ListExperiments"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "ssm:GetParametersByPath"
                ],
                "Resource": "arn:aws:ssm:*:*:parameter/ResilienceHub/*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "s3:GetBucketPolicyStatus",
                    "s3:PutBucketVersioning",
                    "s3:GetBucketTagging",
                    "s3:GetBucketVersioning",
                    "s3:GetReplicationConfiguration",
                    "s3:ListBucket",
                    "s3:ListAllMyBuckets",
                    "s3:GetBucketLocation"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "s3:CreateBucket",
                    "s3:PutObject",
                    "s3:GetObject"
                ],
                "Resource": "arn:aws:s3:::aws-resilience-hub-artifacts-*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "autoscaling:DescribeAutoScalingGroups"
                ],
                "Resource": "*"
            },  
            {
                "Effect": "Allow",
                "Action": [
                    "ec2:DescribeAvailabilityZones",
                    "ec2:DescribeVpcEndpoints",
                    "ec2:DescribeFastSnapshotRestores",
                    "ec2:DescribeInstances",
                    "ec2:DescribeSnapshots",
                    "ec2:DescribeVolumes",
                    "ec2:DescribeNatGateways",
                    "ec2:DescribeSubnets",
                    "ec2:DescribeRegions",
                    "ec2:DescribeTags"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "rds:DescribeDBClusters",
                    "rds:DescribeDBInstanceAutomatedBackups",
                    "rds:DescribeDBInstances",
                    "rds:DescribeGlobalClusters",
                    "rds:DescribeDBClusterSnapshots"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "elasticloadbalancing:DescribeTargetGroups",
                    "elasticloadbalancing:DescribeLoadBalancers",
                    "elasticloadbalancing:DescribeTargetHealth"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "lambda:GetFunction",
                    "lambda:GetFunctionConcurrency",
                    "lambda:ListAliases",
                    "lambda:ListVersionsByFunction"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "ecr:DescribeRegistry"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "backup:DescribeBackupVault",
                    "backup:GetBackupPlan",
                    "backup:GetBackupSelection",
                    "backup:ListBackupPlans",
                    "backup:ListBackupSelections"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "dynamodb:ListTagsOfResource",
                    "dynamodb:DescribeTable",
                    "dynamodb:DescribeGlobalTable",
                    "dynamodb:ListGlobalTables",
                    "dynamodb:DescribeContinuousBackups",
                    "dynamodb:DescribeLimits"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "elasticfilesystem:DescribeMountTargets",
                    "elasticfilesystem:DescribeFileSystems"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "sqs:GetQueueUrl",
                    "sqs:GetQueueAttributes"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "apigateway:GET"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "ecs:DescribeClusters",
                    "ecs:ListServices",
                    "ecs:DescribeServices",
                    "ecs:DescribeCapacityProviders",
                    "ecs:DescribeContainerInstances",
                    "ecs:ListContainerInstances",
                    "ecs:DescribeTaskDefinition"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "route53-recovery-control-config:ListControlPanels",
                    "route53-recovery-control-config:ListRoutingControls",
                    "route53-recovery-readiness:ListReadinessChecks",
                    "route53-recovery-readiness:GetResourceSet",
                    "route53-recovery-readiness:GetReadinessCheckStatus",
                    "route53-recovery-control-config:ListClusters",
                    "route53:ListHealthChecks",
                    "route53:ListHostedZones",
                    "route53:ListResourceRecordSets",
                    "route53:GetHealthCheck"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "drs:DescribeSourceServers",
                    "drs:DescribeJobs",
                    "drs:GetReplicationConfiguration"
                ],
                "Resource": "*"
            }
        ]
    })
  }
}

resource "aws_iam_role" "AwsResilienceHubPeriodicAssessmentRole" {
  name = "AwsResilienceHubPeriodicAssessmentRole"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          Service = "resiliencehub.amazonaws.com"
        }
      },
    ]
  })

  inline_policy {
    name = "AwsResilienceHubPeriodicAssessmentRole_policy"
    
    policy = jsonencode({
        "Version": "2012-10-17",
        "Statement": [
# TODO - PeriodicAssessment hasn't been fully tested yet
# This first block might not be needed, 
# or might need to be hard coded to the acct # where Resil Hub is run from
        {
                "Effect": "Allow",
                "Action": [
                    "iam:GetRole",
                    "iam:PassRole",
                    "sts:AssumeRole"
                ],
                "Resource": "arn:aws:iam::${var.aws_account_id}:role/AwsResilienceHubAdminAccountRole"
        },
            {
                "Effect": "Allow",
                "Action": [
                    "resiliencehub:*"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "sns:GetTopicAttributes",
                    "sns:ListSubscriptionsByTopic",
                    "sns:GetSubscriptionAttributes"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "cloudformation:DescribeStacks",
                    "cloudformation:ListStackResources",
                    "cloudformation:ValidateTemplate"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "servicecatalog:GetApplication",
                    "servicecatalog:ListAssociatedResources"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "resource-groups:ListGroupResources",
                    "resource-groups:GetGroup",
                    "tag:GetResources"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "cloudwatch:DescribeAlarms",
                    "cloudwatch:GetMetricData",
                    "cloudwatch:GetMetricStatistics",
                    "cloudwatch:PutMetricData"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "fis:GetExperimentTemplate",
                    "fis:ListExperimentTemplates",
                    "fis:ListExperiments"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "ssm:GetParametersByPath"
                ],
                "Resource": "arn:aws:ssm:*:*:parameter/ResilienceHub/*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "s3:GetBucketPolicyStatus",
                    "s3:PutBucketVersioning",
                    "s3:GetBucketTagging",
                    "s3:GetBucketVersioning",
                    "s3:GetReplicationConfiguration",
                    "s3:ListBucket",
                    "s3:ListAllMyBuckets",
                    "s3:GetBucketLocation"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "s3:CreateBucket",
                    "s3:PutObject",
                    "s3:GetObject"
                ],
                "Resource": "arn:aws:s3:::aws-resilience-hub-artifacts-*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "autoscaling:DescribeAutoScalingGroups"
                ],
                "Resource": "*"
            },  
            {
                "Effect": "Allow",
                "Action": [
                    "ec2:DescribeAvailabilityZones",
                    "ec2:DescribeVpcEndpoints",
                    "ec2:DescribeFastSnapshotRestores",
                    "ec2:DescribeInstances",
                    "ec2:DescribeSnapshots",
                    "ec2:DescribeVolumes",
                    "ec2:DescribeNatGateways",
                    "ec2:DescribeSubnets",
                    "ec2:DescribeRegions",
                    "ec2:DescribeTags"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "rds:DescribeDBClusters",
                    "rds:DescribeDBInstanceAutomatedBackups",
                    "rds:DescribeDBInstances",
                    "rds:DescribeGlobalClusters",
                    "rds:DescribeDBClusterSnapshots"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "elasticloadbalancing:DescribeTargetGroups",
                    "elasticloadbalancing:DescribeLoadBalancers",
                    "elasticloadbalancing:DescribeTargetHealth"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "lambda:GetFunction",
                    "lambda:GetFunctionConcurrency",
                    "lambda:ListAliases",
                    "lambda:ListVersionsByFunction"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "ecr:DescribeRegistry"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "backup:DescribeBackupVault",
                    "backup:GetBackupPlan",
                    "backup:GetBackupSelection",
                    "backup:ListBackupPlans",
                    "backup:ListBackupSelections"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "dynamodb:ListTagsOfResource",
                    "dynamodb:DescribeTable",
                    "dynamodb:DescribeGlobalTable",
                    "dynamodb:ListGlobalTables",
                    "dynamodb:DescribeContinuousBackups",
                    "dynamodb:DescribeLimits"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "elasticfilesystem:DescribeMountTargets",
                    "elasticfilesystem:DescribeFileSystems"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "sqs:GetQueueUrl",
                    "sqs:GetQueueAttributes"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "apigateway:GET"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "ecs:DescribeClusters",
                    "ecs:ListServices",
                    "ecs:DescribeServices",
                    "ecs:DescribeCapacityProviders",
                    "ecs:DescribeContainerInstances",
                    "ecs:ListContainerInstances",
                    "ecs:DescribeTaskDefinition"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "route53-recovery-control-config:ListControlPanels",
                    "route53-recovery-control-config:ListRoutingControls",
                    "route53-recovery-readiness:ListReadinessChecks",
                    "route53-recovery-readiness:GetResourceSet",
                    "route53-recovery-readiness:GetReadinessCheckStatus",
                    "route53-recovery-control-config:ListClusters",
                    "route53:ListHealthChecks",
                    "route53:ListHostedZones",
                    "route53:ListResourceRecordSets",
                    "route53:GetHealthCheck"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "drs:DescribeSourceServers",
                    "drs:DescribeJobs",
                    "drs:GetReplicationConfiguration"
                ],
                "Resource": "*"
            }
        ]
    })
  }
}
</code></pre></div></div>

<p>Replace <code class="language-plaintext highlighter-rouge">&lt;SSOPermissionSetName&gt;</code>, <code class="language-plaintext highlighter-rouge">&lt;account#ID&gt;</code>, and wildcards as needed.</p>

<p>Note 1: Beware of explicit denies in your S3 bucket policies such as <code class="language-plaintext highlighter-rouge">"Condition": {"ArnNotLike": {"aws:PrincipalARN"}}</code>. The user running Resilience Hub must have permission to the bucket and TF state object (not just these service roles). Legacy Object Ownership ACLs can also interfere with the read of the state object. If you use SSE-KMS, you must also grant the Executor role access to the key(s) via kms: actions.</p>

<p><del>Note 2: Despite what you may have heard or read, you cannot use this service cross-account (at least with TF, not sure about other sources). That is a roadmap feature. For now, you must run Resiliency Hub in the same account where the state file is hosted in S3.</del> (Resolved April 2023)</p>

<p>Note 3: If the Terraform state file references objects in another account, Resiliency Hub’s roles must also have basic permissions (e.g. read/list/describe) to those cross-account objects in order to evaluate their configuration. So the Executor role must exist in the other account with those basic permissions, and the Admin role must exist in the account where the Resilience Hub App is defined, and the Executor role needs to Trust the calling account’s Admin role. This is another area where resource-level access policies can trip you up (looking at you, S3 bucket policies).</p>]]></content><author><name>SeanFromIT</name></author><category term="terraform" /><category term="AWS" /><category term="iam" /><category term="security" /><summary type="html"><![CDATA[The AWS documentation is lacking so here's some Terraform]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://feeney.mba/" /><media:content medium="image" url="https://feeney.mba/" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Microsoft Store 0x87e00017 Error</title><link href="https://feeney.mba/microsoft-store-0x87e00017.html" rel="alternate" type="text/html" title="Microsoft Store 0x87e00017 Error" /><published>2022-12-14T01:00:00+00:00</published><updated>2022-12-14T01:00:00+00:00</updated><id>https://feeney.mba/microsoft-store-0x87e00017</id><content type="html" xml:base="https://feeney.mba/microsoft-store-0x87e00017.html"><![CDATA[<p>If you receive error <strong>0x87e00017</strong> when you try to install an app or game from the Microsoft Store, it indicates that Windows no longer has proper permissions to the folder(s) it uses during download and/or installation. I haven’t dug deep enough to confirm, but presumably, this is D:\WindowsApps and/or D:\Program Files\ModifiableWindowsApps.</p>

<p>I’ve run into this a few times when I’ve carried the drive over from one Windows install to another. wsreset.exe is insufficient to fix the issue; you’ll have to go in and either delete those paths in safe mode or format the drive.</p>

<p>If you’re looking for confirmation that it is a permissions issue, try changing the target drive where ‘New apps will save to’ to D:\ in Settings&gt;System&gt;Storage&gt;Advanced storage settings&gt;Where new content is saved. It will give you a more informative error pointing to permissions.</p>]]></content><author><name>SeanFromIT</name></author><summary type="html"><![CDATA[Root Cause of 0x87e00017 Error]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://feeney.mba/" /><media:content medium="image" url="https://feeney.mba/" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Auto-refresh of boto3 AWS session in 2020</title><link href="https://feeney.mba/refreshable-aws-boto-credentials.html" rel="alternate" type="text/html" title="Auto-refresh of boto3 AWS session in 2020" /><published>2020-10-10T01:00:00+00:00</published><updated>2020-10-10T01:00:00+00:00</updated><id>https://feeney.mba/refreshable-aws-boto-credentials</id><content type="html" xml:base="https://feeney.mba/refreshable-aws-boto-credentials.html"><![CDATA[<p>In a sufficiently large AWS environment, it’s not unusual that a boto3 script may need to run for a long time. However, long runs can lead to timeouts. One solution is to increase the maximum session duration of an assumed role. But what if that’s not an option?</p>

<p>Turns out that by dropping into botocore, you can implement refreshable credentials that will auto-renew as needed. This will prevent timeouts while keeping your security team happy.</p>

<p>This example works for a multi-account, multi-region AWS architecture where a different - but identically named - role is assumed in each account with the IAM permissions necessary for my boto3 method calls. I use a <a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html" title="named profile">named profile</a> with permission to do the assume role.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>import botocore, boto3, datetime
from botocore.session import get_session

accounts = [
    {"name": "Account1", "id": "123456789000"},
    {"name": "Account2", "id": "987654321000"}
]

regions = [ "us-east-1", "us-east-2" ]

# Replace myRole with your local named profile
boto3.setup_default_session(profile_name='myRole')

# 3600 seconds in an hour, this value should match your role's
# maximum session duration (AWS default is 1 hour). If you're
# role chaining (e.g. saml2aws) 1 hour is a hard limit.
def refresh_external_credentials():
    # Assume role, get details
    client = boto3.client('sts')
    credentials = client.assume_role(
        RoleArn=roleArn,
        RoleSessionName="thisNameMattersNot",
        DurationSeconds=3600
    ).get("Credentials")
    return {
        "access_key": credentials.get('AccessKeyId'),
        "secret_key": credentials.get('SecretAccessKey'),
        "token": credentials.get('SessionToken'),
        "expiry_time": credentials.get('Expiration').isoformat()
    }

roleArn = ''

for account in accounts:
    id = account.get('id')
    accountName = account.get('name')
    
    # Replace roleToAssume with your target role
    roleArn = 'arn:aws:iam::' + str(id) + ':role/roleToAssume'
    
    credentials = botocore.credentials.RefreshableCredentials.create_from_metadata(
        metadata=refresh_external_credentials(),
        refresh_using=refresh_external_credentials,
        method="sts-assume-role",
    )
    
    for region in regions:
        session = get_session()
        session._credentials = credentials
        session.set_config_variable("region", region)
        autorefresh_session = boto3.session.Session(botocore_session=session)
        
        # Your boto3 calls, for example...
        rds = autorefresh_session.client('rds')
        databases = rds.describe_db_instances()
        
        # ...
</code></pre></div></div>

<p>This code also available on my <a href="https://github.com/SeanFromIT/Tools/blob/master/boto_refreshablecredentials.py" title="this code on GitHub">GitHub</a>.</p>

<p>Many thanks to the trailblazers:</p>

<ul>
  <li><a href="https://dev.to/li_chastina/auto-refresh-aws-tokens-using-iam-role-and-boto3-2cjf" title="https://dev.to/li_chastina/auto-refresh-aws-tokens-using-iam-role-and-boto3-2cjf">https://dev.to/li_chastina/auto-refresh-aws-tokens-using-iam-role-and-boto3-2cjf</a></li>
  <li><a href="https://www.owenrumney.co.uk/implementing-refreshingawscredentials-python/" title="https://www.owenrumney.co.uk/implementing-refreshingawscredentials-python/">https://www.owenrumney.co.uk/implementing-refreshingawscredentials-python/</a></li>
  <li><a href="https://pritul95.github.io/blogs/boto3/2020/08/01/refreshable-boto3-session/" title="https://pritul95.github.io/blogs/boto3/2020/08/01/refreshable-boto3-session/">https://pritul95.github.io/blogs/boto3/2020/08/01/refreshable-boto3-session/</a></li>
</ul>]]></content><author><name>SeanFromIT</name></author><category term="AWS" /><category term="python" /><summary type="html"><![CDATA[How to auto-refresh a boto3 session when the role has an insufficient session duration limit]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://feeney.mba/" /><media:content medium="image" url="https://feeney.mba/" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>