I don't suppose anyone has done any work with AWS ...
# aws
l
I don't suppose anyone has done any work with AWS Service Catalog & Pulumi? I'm looking to see if I can do some Account Factory shenanigans with Pulumi rather than using the Terraform service catalog 'engine'
s
Do you mind if I reach out via DM to get more information on your use case?
I'm an SA for partnerships at Pulumi and we're gathering requirements for an account factory solution.
l
Sure! I'm UK-based so won't be able to reply in detail until tomorrow, but happy to answer questions
I did notice that Control Tower's API doesn't really seem to be public - they expect you to use the huge Terraform thing, but that seems like a lot to set up, especially since I just want to provision a single Service Catalog product on every account using account factory. I'm fairly tempted to just throw together a dynamic provider that interacts directly with Blackbeard (Control Tower's real backend). It seems like there is at least one project that has done some reverse engineering work on it, though to be honest it doesn't seem like that complex of a service anyway.
s
What's the flow you're imagining to create an account? Who does what in what interface?
l
For a bit more context, I've recently inherited a Control Tower-managed organisation with about 30 accounts. Previously, the org management/control tower was all done manually, simply by navigating to Control Tower -> Account factory and hitting 'Create account'. There were no blueprints or anything deployed to them. I've already championed use of Pulumi across our org, so now that I've taken over management of Control Tower, I'd like to continue using it. I've done some testing in the UI and have created a simple Service Catalog Cloudformation stack 'Product' that makes a GitHub OIDC provider in IAM and a role for our CI runners to assume, giving them access to start managing infra in the account. This can be applied to existing accounts by selecting it in the Control Tower UI and hitting 'Update' with the blueprint selected. I haven't created a new account with it yet, but I assume it's very similar to tell account factory to use the blueprint as well. From that point on, everything is automated with Pulumi. Considering how simple that is, the Account Factory Terraform engine seems insanely overkill - I'm literally just missing two things, and then account creation/updating/bootstrapping would be fully automated: • An equivalent to hitting 'Create account' in Account factory with a blueprint + version from Service Catalog • An equivalent to hitting 'Update' on an account in Control Tower with a blueprint + version from Service Catalog Pulumi already manages the Cloudformation template and creation of the service catalog product, which I'm happy enough with. Arguably there's room for there to be a proper Pulumi 'Engine' (as AWS describes it) to be able to bootstrap accounts via account factory with Pulumi, but for my use-case currently that's by no means a hard requirement.
s
BTW, for context, I'm an SA for partnerships, so this has been on my radar for a while. I believe (and I'm not sure because AWS' docs on this are really hard for me to follow) that an "engine" is the thing that requires a crazy amount of work: a gigantic step function with a ton of different states, etc. If I was trying to bootstrap AWS accounts with baseline infra, and use Pulumi as much as possible, my first design would be something like: 1. Create account in either Control Tower or Service Catalog (not totally sure how this works) 2. Deploy a CFN StackSet that triggers a Lambda (this might be more complicated than necessary - not sure b/c I'm not confident I understand the minimum requirements on AWS' end) 3. The Lambda, either via Pulumi Automation API or a direct REST call triggers the creation of a new stack in the base infra project, and then kicks off Pulumi Deployments 4. A second Lambda is executed on a schedule which checks for updates to the base infrastructure/drift. I would probably default to alerting on drift rather than automatically reconciling, since you would probably want to slowly deploy to any accounts running production workloads.
"Update account" would just be a manual trigger of #4 above. Does that sound like what you also imagined?
l
I've actually sort of combined two different things into my questions here which I think is muddying the water a little, as when I asked the question I hadn't spent quite as much time deciphering the docs as I have now. From what I've gathered, Service Catalog is designed as a service that allows you to create infrastructure 'products', which users in your AWS accounts can then subscribe to on a per-account self-serve basis. That product is then provisioned by an 'engine' (an automated infrastructure-deploying tool) from your catalog account, which by default would be cloudformation, but custom engines that perform provisioning of this product are supported as long as you provision the infrastructure to host them and reply to cloudformation signals and stuff (haven't looked too heavily into this). Control Tower orchestrates Organizations (to create accounts), Guardrails (to apply org-wide policies) and Service Catalog (to bootstrap accounts with base infrastructure and update that base infrastructure stack later - within control tower, a service catalog product that's applied to an account after it's created is called a Blueprint), among other services. If you're using Control Tower to manage accounts, it unfortunately becomes the only way to manage accounts, because doing anything outside of control tower (eg creating an account in the normal AWS Organizations view) causes all sorts of alarms and enrolment issues. Of course, there is no API for Control Tower, so they expect you to do the creation of accounts and applying the blueprints manually. This means that it's essentially impossible for us to use Pulumi to create accounts currently, because creating an account outside of Control Tower is unwise, and Pulumi can't currently create accounts or update the bootstrap product in use by an account (due to the aforementioned lack of API). Under the hood, it looks like Control Tower also uses a special Service Catalog product to create and manage the resource that represents the account in AWS Organisations. So from a technical perspective, I believe that when you create an account via Control Tower and assign a Blueprint to it, it actually provisions two Service Catalog Products: • One that handles all of the Control Tower controls and enrollment and such. I don't think you can realistically affect this product or change the engine it's using in any way. • Your blueprint, which is a self-managed Service Catalog Product, and can use the engine of your choice. Pulumi can import many of the resources that Control Tower creates on your behalf, so you can sort of have them managed by Pulumi after the manual creation. With the current existing APIs, my workflow for bootstrapping an AWS account and adding baseline infra to it looks like this: • Manage the self-managed service catalog product/blueprint (which is simply a cloudformation YAML file - no custom engine in use) in a Pulumi project using a aws.servicecatalog.Product resource (which sort of sucks - the spec is wrong, need to raise a bug report for that). This stack contains a role that my GitHub Actions runners can assume. 1. Manually create an account in Control Tower, with the above product as the 'Blueprint' 2. Manually perform a
pulumi import
of the aws.organizations.Account resource that Control Tower created on my behalf, and define the account in code. 3. Commit the code to GitHub, which triggers CI/CD 4. CD uses the blueprint-defined role to get into the account and deploy the rest of my infra using Pulumi. I don't hate this setup, but in an ideal world I would automate the manual steps 1/2, but am limited by the lack of (public) Control Tower API.
There was so many aws service names in that message, good lord
s
This all roughly matches my understanding - you have to initiate the creation of an account from within either SC or CT. You can do that "gitops" style with AFTerraform, or you can do it via the UI in SC/Cfn (which I've definitely seen) or maybe CT (which I've never used firsthand). Have you looked into triggering a Lambda which could use Auto API to kick off a new stack, and then automatically deploy via Pulumi Deployments?
l
If my understanding is correct, the creating of new accounts must be done via Control Tower, as it seems to use Service Catalogue in way that isn't accessible via its publically-available APIs in order to keep CT's state correct. The product 'type' in Service Catalogue is a special
CONTROL_TOWER_ACCOUNT
value, which isn't available via the normal api That's why I'm stuck on the setup I have now, because I don't think there's a way to automate account creation in Control Tower without using AFT, which does a lot of additional stuff to make that work and line up with CT's expected state. I've looked through the code to try and figure out what black magic it performs to do this and not have CT freak out, but it's a gigantic project and it's quite difficult to parse. Edit: Having re-read your message, I now understand that you meant using the lambda + automation api to trigger the post-creation provisioning process after a new account has been manually created. I quite like this idea! It doesn't solve the initial creation issue, but does smoothen out the process a little bit. I just had a read of pulumi's docs and it looks like the automation API supports performing imports, which is quite cool. I do want to bring up pulumi/pulumi#17640 which I raised a while back though, as that could simplify it even further and perhaps even avoid the need to write import logic using the autoamtion api
s
I think you're gonna have some sort of Pulumi program that represents your account baseline (Config Rules, maybe a VPC with centralized egress, assumable roles, stuff like that). Then, creating a new account triggers a Lambda that uses Auto API to create a new stack of the account baseline with the details of the new account. I would delegate running
pulumi up
to Pulumi Deployments, assuming you're on Pulumi Cloud. Check out this article: https://aws.amazon.com/blogs/mt/developing-an-aws-service-catalog-self-managed-engine-for-governance/ I do plan to create this reference architecture with Pulumi at some point in the coming year, but I would imagine you're not necessarily thrilled to have to wait that long.
So creating a new account still needs to be done via Service Catalog (I think?), but even that should be automatable. I'm assuming SC has an API.
l
So creating a new account still needs to be done via Service Catalog
Nope - If you're using Control Tower, accounts must be created via Control Tower or AFT 😞
s
Well this is confusing. I thought the whole point of this generic
EXTERNAL
engine in SC was because the license changes in TF necessitated it, and that that was the golden path going forward.
l
Control Tower utilises SC to do account creation, but in a way that's opaque to the user and has no automation controls. After the account has been created, then you can use the
EXTERNAL
engine to bootstrap infra on the new account.
s
So it would need to be a manual two-step process: 1) create a new account in CT 2) deploy the SC product that does the account baseline in Pulumi?
l
From what I can tell, yes
s
This is helpful. I'm gonna dig in with AWS and see if I can either confirm or figure out a smoother way.
Are you working an
EXTERNAL
product implementation with Pulumi?
l
Not currently - I went with a much more simplified approach. I perform the creation of the account manually with CT, then apply a very simple cloudformation SC product which deploys a role that my CI/CD runners can use to access the account. Then I just commit the account details to git, which triggers CD to assume that role and perform bootstrapping with Pulumi. It isn't quite as GitOps as one would hope, but it's pretty fluid