Superwerker AWS Control Tower deployment fails with invalid AWS Regions

The function’s code payload is here:

<s3://superwerker-assets-us-west-2/0.0.0-DEVELOPMENT/78fe57d5e418511e488ec4d02480d75ac3993b95bd71fa37b5667287c716263c.zip>

It contains lots of files. It looks like a Python-runtime Lambda. That’s a good sign. I think Superwerker still uses the <https://github.com/schubergphilis/awsapilib|awsapilib Python library> to set up some parts of Control Tower.

Yes, we are getting somewhere. The handler function in that zip’s index.py uses awsapilib to set up Control Tower.

The function call to start the process doesn’t specify any regions. So it doesn’t look the error is provoked because of any user input.

            logging_account_email=logging_account_email,
            security_account_email=audit_account_email,
            retries=50,
            wait=5
        )```

The deploy function has some code for deriving a region list. I think this might be what we need to check to understand why you get that error.

Are you looking in the github?

I cloned the awsapilb repo that I linked just above.

Th deploy function is in a file called controltower.py.

Oh god :joy: The code has to call out to another weird AWS thing to get the list of available Control Tower regions.

    def get_available_regions():
        """The regions that control tower can be active in.

        Returns:
            regions (list): A list of strings of the regions that control tower can be active in.

        """
        url = '<https://api.regional-table.region-services.aws.a2z.com/index.json>'
        response = requests.get(url, timeout=5)
        if not response.ok:
            LOGGER.error('Failed to retrieve the info')
            return []
        return [entry.get('id', '').split(':')[1]
                for entry in response.json().get('prices')
                if entry.get('id').startswith('controltower')]```

It seems to get information about Control Tower regions from here:

<https://api.regional-table.region-services.aws.a2z.com/index.json>

I want to note this is also a fresh aws account

Yeah, you said so. Unfortunately that doesn’t make it more likely that Superwerker or awsapilib don’t suddnenly break one day. These tools are not made by AWS so AWS can change things without warning that break those tools.

For sure, I’m just trying to convince myself its not a config I done :laughing:

awsapilib is a volunteer attempt by one heroic enthusiast to reverse-engineer the missing APIs for Control Tower.

It’s one of AWS’s best “thankless in Nebraska” moments. https://xkcd.com/2347/

You’d thing that the exception I’m seeing would be asserted here if there was an issue with awsapilib

def _validate_regions(self, regions):
available_regions = self.get_available_regions()
if not set(available_regions).issuperset(set(regions)):
raise UnavailableRegion(set(regions) - set(available_regions))
return regions

That JSON file from the a2z domain says that Control Tower is available in two GovCloud regions. I think this may be where the problem starts.

cat services.json | jq '.prices[] | select((.id | contains("controltower")) and (.id | contains("gov")))' | less

  "attributes": {
    "aws:region": "us-gov-west-1",
    "aws:serviceName": "AWS Control Tower",
    "aws:serviceUrl": "<https://aws.amazon.com/controltower>"
  },
  "id": "controltower:us-gov-west-1"
}
{
  "attributes": {
    "aws:region": "us-gov-east-1",
    "aws:serviceName": "AWS Control Tower",
    "aws:serviceUrl": "<https://aws.amazon.com/controltower>"
  },
  "id": "controltower:us-gov-east-1"
}```

The get_available_regions function looks like it returns a list of all the regions in that file for the controltower service.

So the list it returns will contain those GovCloud regions.

I’m checking the _validate_regions function now to check your question about error assertions.