Skip to main content

Process: Onboarding

What is this process and why do I care about it?

Event Processing Workflow delivers the core value of Pyrae Policy Engine. It is responsible for executing the Observers, evaluating Policies, storing changes for Violations, and triggering Integrations.

Prerequisites

This process is pretty long, so this is the list to complete everything, but you can get started and figure it out as you go along.

  1. An executed service agreement with Pyrae Inc.
  2. A person within your organization designated as the contact person, who shall be the point person to initiate cross-company communication. Pyrae will reciprocate with an Account Manager. Name + Email
  3. A person within your organization designated as the onboarding individual, who will complete the procedure outlined here. This may be separate from the contact person. Name + Email
  4. Optionally, you may request a Slack Connect channel for more efficient communication. This will require a Slack Administrator on your end to confirm the channel.
  5. Decide upon an organization name, which will be your subdomain at [subdomain].app.pyrae.com, which is where your employees will go to log in.
  6. A Git repository to store the configuration for Pyrae.
  7. A list of Users (employees) that you wish to grant access to Pyrae
  8. A Team hierarchy that you wish to create in Pyrae
    1. A list of Users that are on that team
  9. A list of Bundles ("projects") that you will use to logically group resources in your AWS account
    1. A designated owning Team for each bundle
    2. A good starting point is: one Bundle per Team.
  10. A list of AWS accounts that you wish to onboard to Pyrae, noting for each:
  11. The AWS account ID
  12. The default owner Bundle for the account, to be used when a Resource doesn't have an explicit owner.
  13. A list of Integrations that you wish to configure.

Process

Org Provisioning

As part of executing the service agreement, a Pyrae representative should ask you for this information:

  1. Your preferred organization name, which will be your subdomain at [subdomain].app.pyrae.com, which is where your employees will go to log in.
  2. A designated contact person, who shall be the point person to initiate cross-company communication. Pyrae will reciprocate with an Account Manager. Name + Email
  3. A designated onboarding individual, who will complete the procedure outlined here. This may be separate from the contact person. Name + Email
  4. Whether you want a Slack Connect channel for more efficient communication. This will require a Slack Administrator on your end to confirm the channel.

Pyrae will initialize the bare-bones organization, and Pyrae will respond with:

  1. The chosen Organization Name (subdomain)
  2. The "Organization ID", which will be present in the 'Account ID' field of all Pyrae-issued URNs for your organization.
  3. A Root User, a non-deletable administrative Pyrae UI User, with credentials sent to the Onboarding Person's Email.

Git Repository Setup

There is no mandatory structure at this time, nor is there any Pyrae-provided tooling (eg, CICD) for this repository at this time. So, the structure of this repository is entirely up to you, h couowever, we have a recommendation.

We recommend creating a folder named "stacks", with one file in per Stack, giving that file the name of the Stack. Currently, stacks that span across multiple files are not possible without preprocessing to prepare a single template file.

If you're just trying to get started, the most frictionless way is to put everything into one big stack. It's not much work to divide it later. Any stack can contain any resource definitions that you'd like. You should group definitions based on how likely they are to change together.

Minimal example, for a small-ish company:

gitroot/
.git/
stacks/
users.yaml
teams.yaml
bundles.yaml

If you're feeling fancy, and want to leverage code owners, you can create subfolders for each team, like this:

gitroot/
.git/
stacks/
cloudops/
cloudops-users.yaml
cloudops-bundles.yaml
pipeline-team/
pipeline-team-main.yaml

Create a Quickstart template

Create a Stack file named quickstart.yaml. Pre-populate it with this:

Version: 1
OfnResources:
// TODO

Onboard AWS Accounts

This is a multi-step process on its own, which, at this point, can be performed in parallel with the rest of this guide This is recommended to start early because this process is not fully-self-service yet; you will need to schedule time with your Account Manager to fully onboard the Accounts.

You will need:

  1. A list of AWS accounts that you wish to onboard to Pyrae, noting for each:
    1. The AWS Account ID of each account
    2. The default owner Bundle for each account, to be used when a Resource doesn't have an explicit owner.
      1. The Bundles actually don't need to exist yet, you just need to know what they will be named. This is a perk of Pyrae's thorough embrace of URNs
    3. The desired owner identification strategy for each account. All into one bundle, owner tag, or custom lambda.

The full AWS Account Onboarding process is here.

We're going to add resources to this over the coming few steps

Define Teams/Team Hierarchy

You will need at least one Team.

Teams own Bundles (which own Resources), and Teams have Users ("members").

Your template should look like:

Version: 1
OfnResources:
MyTeam:
Type: "Pyrae::IAM::Team"
Properties:
Name: "MyTeam"

If you wish to define a team that is a sub-team of another Team (which will cause it to inherit all of the signed policies of the parent team), you would write it like this:

Version: 1
OfnResources:
MyTeam:
# ...
MySubTeam:
Type: "Pyrae::IAM::Team"
Properties:
Name: "MySubTeam"
## IF MyTeam is defined in the same stack
ParentTeamUrn: { PyRef: MyTeam }
## IF MyTeam is not defined in the same stack, you need to write the full URN of the other team
ParentTeamUrn: "urn:pyrae:iam::[your-org-id]:team/MyTeam`

FYI, PyRef works for any URN-based reference to another object, so long as those objects are defined in the same Stack.

Define at least one Bundle per Team

Bundles own Resources. If a Team is capable of owning anything, it must have at least one Bundle.

Your template should look like this:

Version: 1
OfnResources:
MyTeam:
# ...
MyTeamsBundle:
Type: "Pyrae::IAM::Bundle"
Properties:
Name: "MyTeamsBundle" # When using the Tag owner identification strategy, this is the value of the `pyrae:OwnerTag` key.
Owner:
TeamUrn: { PyRef: MyTeam }

Define Users

Create a SelfManagedUser for each person that needs access to the Pyrae UI. Any individual responsible for handling violations, developing policies, or managing those people should probably have access.

Note that for the time being, all users have permission to deploy and modify OFN stacks thru the OFN UI.

Your template should look like this:

Version: 1
OfnResources:
MyTeam:
# ...
MyTeamsBundle:
# ...
JohnDoe:
Type: "Pyrae::IAM::SelfManagedUser"
Properties:
Name: "johndoe"
Username: "johndoe"
ManagerUsername: "janedoe"
# there are other attributes you could define, but this is the minimum required for the next step

Add Users to Teams

Create TeamMembershipRules to add Users to Teams. These Rules look at the attributes of the User object to determine membership.

Note that this is just used for customizing the UI experience. This does not regulate access/visibility.

Here's some sample rules:

Version: 1
OfnResources:
MyTeam:
# ...
MyTeamsBundle:
# ...
JohnDoe:
# ...
MyTeamMemberJohnDoe:
Type: "Pyrae::IAM::TeamMembershipRule"
# Match based on their Username
Properties:
TargetTeamUrn: { PyRef: MyTeam }
Username: "johndoe"
# Or, match based on their manager's username:
Properties:
TargetTeamUrn: { PyRef: MyTeam }
ManagerUsername: "janedoe"
# Or, match everyone:
Properties:
TargetTeamUrn: { PyRef: MyTeam }
# Or use any combination of fields, as needed

The Org identified by the Org ID sAutx4ZxiqTJUzJdvky2km is an administrative Org managed by Pyrae. This is where we deploy the Policies/Observers developed by Pyrae. If you wish to use those Policies, you need to create an OrgLink. OrgLinks are responsible for pushing/pulling sharable resources, such as Policies, across Org boundaries. OrgLinks require two objects to be complete, one in each Org; one in Push configuration and the other in Receive configuration. Since we wish to Receive objects from the administrative Org, we need to create an OrgLink in Receive configuration:

Version: 1
OfnResources:
# ...
PyraeOrgLink:
DemoCustomerTeamLink:
Type: Pyrae::Org::Link
Properties:
RemoteOrgUrn: "urn:pyrae:org::sAutx4ZxiqTJUzJdvky2km:org/sAutx4ZxiqTJUzJdvky2km"
ReceiveObjects: true

The administrative Org is special, and will automatically reciprocate by completing the link.

There is nothing strictly requiring this link to be created, if you wish to opt out of all Pyrae policies. But this guide requires it for the following steps.

Sign some Policies

For the time being, we're just going to sign one policy -- particularly, one that is easy to flip between in Violation/not in Violation. This will be useful for exercising the Integration later on.

This policy is the Lambda Architectures policy. It enforces that all AWS Lambdas use arm64, which costs less than x86_64. So, we'll be able to easily exercise it by creating a new Lambda, and swapping its configured architecture.

Version: 1
OfnResources:
# ...
MyTeamSignedLambdaArchitectures:
Type: Pyrae::Policy::PolicyDocument::Signatory
Properties:
SignatureTeamUrn: { "PyRef": "PyraeTeam" }
PolicyUrn: "urn:pyrae:policy:us-west-2:sAutx4ZxiqTJUzJdvky2km:policy/lambdaArchitecturesPolicy"

Deploy the Template

Go to the OrgFormation UI, and upload your template file to a new stack.

You can confirm the result by waiting for the deployment to complete, then looking at the "Resources" tab of the stack, and checking for any missing resources. If one is missing, check the "Events" tab for the error message.

Test the Policy

You need to have completed the AWS Account onboarded to perform a test.

Create an AWS Lambda function. Just use the default/empty function body; we don't need to be able to execute it. Use arm64 for now, so that the lambda is not in violation.

Take the ARN of the AWS Lambda function. Paste it into the search bar at the top of the Pyrae UI. You'll be taken to the Resource page. If the resource doesn't exist (404), then you might have to wait a bit longer; CloudTrail typically takes fifteen minutes to notify of a new batch of changes.

On the Resource page, you should see a "Violations" tab. That should be an empty list, indicating that the Resource has no open Violations.

Now, edit the lambda to use x84_64, and wait about fifteen minutes. You should see a violation when you refresh the Resource page.

Clicking into the Violation page, you can see the Observance history that resulted in this violation, as well as links to the related Policy, etc.

Set up an Integration

An Integration defines how to interact with a third party.

An IntegrationViolationTriggerRule defines when a violation should use that third party integration by matching against the violation that's opened/closed.

You'll need both. Deploy this, then change the lambda to be in or out of violation, and you should see a slack message show up within 15 minutes.

Version: 1
OfnResources:
# ...
MyTeamIntegration:
Type: Pyrae::Integration::Integration
Properties:
OwnerTeamUrn: { "PyRef": "PyraeTeam" }
IntegrationType: "SLACK"
MetadataJson: '{"slack_token": "123451234512345123451234512345", "channel": "C123123123"}'
MyTeamIntegrationTriggerRule:
Type: Pyrae::Integration::ViolationTriggerRule
Properties:
IntegrationUrn: { "PyRef": "MyTeamIntegration" }
MatchTeamUrn: { "PyRef": "PyraeTeam" }
UseExprPreset: SLACK_SEND_MESSAGE_TO_CHANNEL